2012-07-19 48 views
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,诠释nBlockUse)线1376 + 0x3b字节C++
msvcr100d.dll _free_dbg(void *的pUserData,诠释nBlockUse)线1265 + 0xd bytes C++
msvcr100d.dll!free(void * pUserData)line 49 + 0xb bytes C++
New.exe!gb2Utf8(const char * source,int sourceLen,void * target,int targetLen)Line 156 + 0xc字节C++
New.exe!wWinMain(HINSTANCE__ * hInstance,HINSTANCE__ * hPrevInstance,wchar_t * lpCmdLine,int nCmdShow)第29行+ 0x11字节C++
N ew.exe!__ tmainCRTStartup()线547 + 0x2c上字节Ç
New.exe!wWinMainCRTStartup()线371℃
KERNEL32.DLL!7509339a()下面
[帧可以是不正确的和/或缺失,无符号加载为KERNEL32.DLL]
NTDLL.DLL!77979ef2()
NTDLL.DLL!77979ec5()

+0

坦克大家都在寻求帮助,这个函数有两个错误。 – user805627 2012-07-19 05:10:52

回答

1

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

正如Jeeva所说,调用此函数的正确方法是使用NULL输出缓冲区调用一次,按所需大小分配缓冲区,然后再次调用它。

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) ; 
+0

此问题标记为'c',你的回答是无效的C代码。 – 2012-07-19 05:00:07

+0

我应该改变新的和删除与malloc和免费的? – Jeeva 2012-07-19 05:01:08

+0

这会使它成为C代码,是的。 – 2012-07-19 05:01:24

3

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

int bufLen = strlen(source) * 2 + 2; 
+0

更好,请使用'sizeof(WCHAR)'。 – 2012-07-19 04:59:12

1

首先,让我们来看看:

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

如果malloc函数失败,它返回NULL,然后buffer被赋值为NU LL,那么程序由于goto RETURN而转向标签RETURN,然后free函数被调用,free(buffer)表示free(NULL),这是非法行为。

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

此外,您最好仔细查看功能MultiByteToWideChar的使用情况。这里是MSDN中的链接:MultiByteToWideChar function

+0

谢谢,但免费的NULL指针是合法行为。 'free()函数释放ptr指向的内存分配。如果ptr是一个NULL指针,则不执行任何操作。' - 从手册页 – user805627 2012-07-19 05:23:52

+0

对不起我的错误。在检查了C99文档后,我意识到空闲(NULL)是合法的。然而,很久以前,我的老师教过我这一点,我只是相信他而不检查出来。再次抱歉。 – 2012-07-19 05:28:19

+0

以下是C99文档中的描述:自由函数使得ptr指向的空间被释放,即可用于进一步分配。如果ptr是空指针,则不会发生任何操作。否则,如果参数与先前由calloc,malloc或realloc函数返回的指针不匹配,或者如果空间已通过释放或realloc调用释放,则行为未定义。 – 2012-07-19 05:32:43