繁体   English   中英

为什么在释放内存时此功能总是崩溃?

[英]Why does this function always crash when free memory?

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()

您不必自己假设缓冲区大小,将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) ;

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

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

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

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

首先,让我们看一下:

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

如果malloc函数失败,它返回NULL,然后buffer被分配NULL值,则程序转向标记RETURN由于goto RETURN ,然后free函数被调用和free(buffer)装置以free(NULL)这是一个非法行为。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM