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)とクラッシュしますが、理由はわかりません。定数値に
変更したり、関数を削除したりしても、クラッシュすることはありません。理由もわかりません。これは、クラッシュ時のコールスタックです。bufLenMultiByteToWideChar

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バイト
CNew.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、終端の null 文字を含むバッファ サイズが返されます。次に、返されたサイズでバッファを作成して使用できます。

これを試して

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

の最後のパラメーターMultiByteToWideChar()は、ワイド文字バッファー内の文字数であり、バイト数ではありません。バイト数を渡すと、関数はおそらく実際のバッファを上書きしfree()、デバッグ モードでコンパイルされたときにそれをチェックします。

そして、Jeeva が述べたように、この関数を呼び出す適切な方法は、NULL 出力バッファーで一度呼び出し、要求されたサイズのバッファーを割り当ててから、再度呼び出すことです。

于 2012-07-19T04:54:35.157 に答える
1

まず、次を見てみましょう。

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

malloc関数が失敗した場合、NULL が返され、値 NULL が割り当てられた場合、プログラムはによりbufferラベルに変わり、関数が呼び出されて を意味します。これは不正な動作です。RETURNgoto RETURNfreefree(buffer)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 に答える