C 为什么这个函数在释放内存时总是崩溃?

C 为什么这个函数在释放内存时总是崩溃?,c,winapi,memory-management,C,Winapi,Memory Management,当程序运行到空闲(缓冲区)时,它会崩溃,但我不知道为什么。 如果将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

当程序运行到
空闲(缓冲区)
时,它会崩溃,但我不知道为什么。
如果将
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!空闲(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_*HPPreInstance,wchar_*lpCmdLine,int nCmdShow)第29+0x11行字节C++
New.exe__tmainCRTStartup()行547+0x2c字节C
New.exe!wwinmincartstartup()行371 C
内核32.dll!7509339a()
[下面的帧可能不正确和/或丢失,没有为kernel32.dll加载符号]
ntdll.dll!77979ef2()
ntdll.dll!77979ec5()


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


正如Jeeva所提到的,调用此函数的正确方法是使用NULL output buffer调用它一次,按照请求的大小分配缓冲区,然后再次调用。

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


正如Jeeva提到的,调用此函数的正确方法是使用NULL output buffer调用它一次,使用请求的大小分配缓冲区,然后再次调用它。

您无需自行假设缓冲区大小,当您将0作为最后一个参数传递给函数
MultiByteToWideChar
时,它返回缓冲区大小,包括终端空字符。然后可以使用返回的大小创建缓冲区并使用它

试试这个

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;
}

当您将0作为最后一个参数传递给函数
MultiByteToWideChar
时,您无需自行假定缓冲区大小,它将返回缓冲区大小,包括终端空字符。然后可以使用返回的大小创建缓冲区并使用它

试试这个

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;
}

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

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

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

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) ;
首先,让我们看看:

int bufLen = strlen(source) * 2 + 2;
如果
malloc
函数失败,它返回NULL,然后
buffer
被赋值为NULL,然后由于
goto RETURN
,程序转到label
RETURN
,然后调用
free
函数,并且
free(buffer)
意味着
free(NULL)
,这是非法行为

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

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

首先,让我们看看:

int bufLen = strlen(source) * 2 + 2;
如果
malloc
函数失败,它返回NULL,然后
buffer
被赋值为NULL,然后由于
goto RETURN
,程序转到label
RETURN
,然后调用
free
函数,并且
free(buffer)
意味着
free(NULL)
,这是非法行为

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


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

更好的方法是使用
sizeof(WCHAR)
。更好的方法是使用
sizeof(WCHAR)
。我应该使用malloc和free更改new和delete吗?
malloc
的参数是字节数,而不是元素数(它甚至不知道元素类型)。我应该使用malloc和free更改new和delete吗?
malloc
的参数是字节数,而不是元素数(它甚至不知道元素类型)。Tank各位需要帮助,此函数中有两个错误。Tank各位需要帮助,此函数中有两个错误。谢谢,但释放空指针是一种合法行为。”函数的作用是:释放ptr指向的内存分配。如果ptr是空指针,则不执行任何操作。“-从手册页抱歉我的错误。在检查了C99文档之后,我意识到免费(NULL)是合法的。然而,很久以前,我的老师教我这个,我只是相信他没有检查出来。再次抱歉。以下是C99文档中的描述:free函数导致ptr指向的空间被释放,也就是说,可用于进一步分配。如果ptr是空指针,则不会发生任何操作。否则,如果参数与calloc、malloc或realloc函数先前返回的指针不匹配,或者如果通过调用free或realloc释放了空间,则行为未定义。谢谢,释放空指针是合法行为。”函数的作用是:释放ptr指向的内存分配。如果ptr为空