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

时间:2014-04-10 15:30:43

标签: c++ arrays pointers boost-asio delete-operator

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

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

  

Debug Assertion失败:

     

计划:[...] \DataSender.exe
  档案:f:\dd\vctools\crt_bld\self_x86\crt\src\dbgdel.cpp
  行:52

     

表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

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

但是当我尝试在循环结束时再次删除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指针数组时我做错了什么但是我还没想到它。

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

2 个答案:

答案 0 :(得分:1)

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

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

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

当你这样做时

char* buffer = new char[bufferSize];
<*>在if范围中,您创建了一个新变量,而不是将内存分配到外部buffer变量中。因此,您正在泄漏,而不是将内存分配到刚刚删除的缓冲区中。

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

答案 1 :(得分:0)

我会使用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()函数的返回值)。相反,您假设返回了bufferSize字符。

相关问题