我正在编写一个使用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指针数组时我做错了什么但是我还没想到它。
有人能指出我正确的方向吗?
答案 0 :(得分:1)
当remainingBytes
和receivedBytes
小于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字符。