2012-07-19 45 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