尝试释放字符数组的指针时出错:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

Error when trying to deallocate pointer of char array: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

本文关键字:pHead- VALID IS nBlockUse TYPE BLOCK 数组 字符 释放 指针 出错      更新时间:2023-10-16

我正在编写一个使用 Boost.Asio 发送和接收图像的C++程序。

编译时我没有收到错误,但是在执行并发送图像时,接收图像的程序崩溃,并显示以下错误消息(在Visual Studio 2012中,Windows 7 32位(:

调试断言失败:

程序: [...]DataSender.exe 文件: f:ddvctoolscrt_bldself_x86crtsrcdbgdel.cpp
行: 52

表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

我将 4096 字节大小的包读入指向 char 数组的指针中,同时仍有传入字节要读取。在最后一个循环中(如果要读取的字节少于 4096 个(,我将删除指针并创建一个指向剩余字节大小的字符数组的指针。直到这里它仍然有效。

但是当我尝试在循环结束时再次删除 char 指针数组时(以便为下一个传入图像创建一个标准大小为 4096 的新 char 指针数组(,程序崩溃了。

这是我的代码摘录:

char* buffer = new char[4096];

[...]

int remainingBytes = imageSize;

[...]

// read data
while( remainingBytes > 0 )
{
    boost::system::error_code error;
    // use smaller buffer if remaining bytes don't fill the tcp package
    // fully
    if( remainingBytes < 4096 )
    {
        delete[] buffer; // this one doesn't give an error
        bufferSize = remainingBytes;
        char* buffer = new char[bufferSize];
    }
    // read from socket into buffer
    size_t receivedBytes = socket.read_some(
            boost::asio::buffer(buffer, bufferSize), error);
    remainingBytes -= receivedBytes;
    // count total length
    totalReceivedBytes += receivedBytes;
    // add current buffer to totalBuffer
    for( int i = 0; i < bufferSize; i++)
    {
        totalBuffer.push_back(buffer[i]);
    }
    // if smaller buffer has been used delete it and
    // create usual tcp buffer again
    if( receivedBytes < 4096 )
    {
        delete[] buffer; // here the error occurs
        bufferSize = 4096;
        char* buffer = new char[bufferSize];
    }
}

我也在 Debian GNU/Linux 7.2 64 位机器上运行了相同的代码,它在代码中的相同位置返回了以下错误:

*** glibc detected *** ./datasender: double free or corruption (!prev): 0x0000000002503970 ***

我假设我在解除分配 char 指针数组时做错了什么,但我还没有弄清楚。

有人可以指出我正确的方向吗?

remainingBytesreceivedBytes小于 4096 时,您实际上删除了两倍的缓冲区。

实际上,您删除buffer一次,然后将内存分配给本地buffer,而不是外部

然后,当您删除第二个 if 块中的buffer时,您将再次删除相同的缓冲区。在 if 作用域中进行的分配是内存泄漏。这些变量不同。

当你这样做时

char* buffer = new char[bufferSize];

在 If 作用域中,你正在创建一个新变量,而不是将内存分配到外部buffer变量中。因此,您正在泄漏,并且没有将内存分配到刚刚删除的缓冲区中。

无需进一步查看,您应该删除两个 if 块中buffer前面的char*,然后继续调试。

我会改用std::vector:

#include <vector>
//...
std::vector<char> buffer(remainingBytes);
bufferSize = remainingBytes;
//...
while( remainingBytes > 0 )
{
    boost::system::error_code error;
    // use smaller buffer if remaining bytes don't fill the tcp package
    // fully
    if( remainingBytes < 4096 )
    {
       buffer.resize(remainingBytes);
       bufferSize = remainingBytes;
    }
    // read from socket into buffer
    size_t receivedBytes = socket.read_some(
            boost::asio::buffer(&buffer[0], bufferSize), error);
    remainingBytes -= receivedBytes;
    // count total length
    totalReceivedBytes += receivedBytes;
    // add current buffer to totalBuffer
    totalBuffer.insert(totalBuffer.end(), buffer.begin(), 
                                          buffer.begin() + receivedBytes);
    // if smaller buffer has been used delete it and
    // create usual tcp buffer again
    if( receivedBytes < 4096 )
    {
        buffer.resize(4096);
        bufferSize = 4096;
    }
}

不会有内存泄漏。

另外,我认为您的代码有一个错误,因为您应该只复制接收的字节数(read_some(( 函数的返回值(。 相反,您假定返回了缓冲区大小字符。