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)Line 1376 + 0x3b bytes 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()
答案 0 :(得分:3)
当您将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) ;
答案 1 :(得分:3)
也许对于缓冲区,您还需要为NULL终止符分配内存:
int bufLen = strlen(source) * 2 + 2;
答案 2 :(得分:1)
MultiByteToWideChar()
的最后一个参数是widechar缓冲区中字符的数量,而不是字节数。您传递了字节数,该函数可能会在实际缓冲区中进行写入,并且在调试模式下编译时会free()
检查该函数。
正如Jeeva所说,调用此函数的正确方法是使用NULL输出缓冲区调用一次,分配具有请求大小的缓冲区,然后再次调用它。
答案 3 :(得分:1)
首先,我们来看看:
if (!buffer)
{
result = 1;
goto RETURN;
}
如果malloc
函数失败,则返回NULL,然后buffer
被赋值NULL,然后由于RETURN
,程序转向标签goto RETURN
,然后{调用{1}}函数,free
表示free(buffer)
,这是一种非法行为。
其次,通过声明free(NULL)
,您假设int bufLen = strlen(source) * 2;
将始终为正,但是,如果strlen(source)== 0,则它将为0。 malloc(0)是ANSI-C中未定义的行为,因此不同的平台可能会返回不同的结果。
此外,您最好仔细查看函数bufLen
的用法。以下是MSDN中的链接:MultiByteToWideChar function