1
int gb2Utf8(const char* source, int sourceLen, void *target, int targetLen)
{
    int result = 0;
    int bufLen = strlen(source) * 2;
    wchar_t *buffer = (wchar_t *)malloc(bufLen);
    if (!buffer)
    {
        result = 1;
        goto RETURN;
    }

    //GB18030 code page: 54936
    int m2wResult = MultiByteToWideChar(54936, MB_ERR_INVALID_CHARS, source, -1, buffer, bufLen);
    if (!m2wResult)
    {
        result = 2;
        goto RETURN;
    }

    int w2mResult = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, buffer, -1, (char *)target, targetLen, NULL, NULL);
    if (!w2mResult)
    {
        result = 3;
        goto RETURN;
    }

    RETURN:
    free(buffer);
    return result;
}

当程序运行到 时free(buffer),它会崩溃,但我不知道为什么。
如果修改bufLen成一个常数值,或者删除MultiByteToWideChar函数,它不会崩溃,我也不知道为什么。这是崩溃时的调用堆栈:

msvcr100d.dll!_free_dbg_nolock(void * pUserData, int nBlockUse) 第 1376 行 + 0x3b 字节 C++
msvcr100d.dll!_free_dbg(void * pUserData, int nBlockUse) 第 1265 行 + 0xd 字节 C++
msvcr100d.dll!free(void * pUserData) 第 49 行+ 0xb 字节 C++
New.exe!gb2Utf8(const char * source, int sourceLen, void * target, int targetLen) 第 156 行 + 0xc 字节 C++
New.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) 第 29 行 + 0x11 字节 C++
New.exe!__tmainCRTStartup() 第 547 行 + 0x2c 字节 C
New.exe!wWinMainCRTStartup() 第 371 行 C
kernel32.dll!7509339a()
[下面的帧可能不正确和/或丢失,否为 kernel32.dll 加载的符号]
ntdll.dll!77979ef2()
ntdll.dll!77979ec5()

4

4 回答 4

3

也许对于缓冲区,您也需要为 NULL 终止符分配内存:

int bufLen = strlen(source) * 2 + 2;
于 2012-07-19T04:55:13.073 回答
2

您不需要自己假设缓冲区大小,当您将 0 作为最后一个参数传递给函数MultiByteToWideChar时,它会返回缓冲区大小,包括终端空字符。然后您可以使用返回的大小创建缓冲区并使用它。

试试这个

int wchars_num =  MultiByteToWideChar( CP_UTF8 , 0 , source , -1, NULL , 0 );
wchar_t* buffer = (wchar_t *)malloc(wchars_num);

MultiByteToWideChar( CP_UTF8 , 0 , source  , -1, buffer , wchars_num );
// do whatever with buffer 
free(buffer) ;
于 2012-07-19T04:54:44.887 回答
1

for的最后一个参数MultiByteToWideChar()是宽字符缓冲区中的字符数,而不是字节数。您传递字节数,该函数可能会写入实际缓冲区并free()在调试模式下编译时检查该缓冲区。

正如 Jeeva 所提到的,调用此函数的正确方法是使用 NULL 输出缓冲区调用它一次,分配具有请求大小的缓冲区,然后再次调用它。

于 2012-07-19T04:54:35.157 回答
1

首先,让我们看一下:

if (!buffer)
{
    result = 1;
    goto RETURN;
}

如果malloc函数失败,它返回 NULL,然后buffer被赋值为 NULL,然后程序转向标签RETURN由于goto RETURN,然后free函数被调用并且free(buffer)意味着 to free(NULL),这是一种非法行为。

其次,通过声明int bufLen = strlen(source) * 2;,您假设它bufLen始终为正数,但是,如果 strlen(source)==0,它将为 0。malloc(0) 是 ANSI-C 中未定义的行为,因此不同的平台可能会返回不同的结果。

此外,您最好仔细查看函数的用法MultiByteToWideChar。这是 MSDN 中的链接:MultiByteToWideChar 函数

于 2012-07-19T05:12:45.347 回答