C++ 位置接近100KB时memcpy上的segfault
我试图“打包”一个大的C++ 位置接近100KB时memcpy上的segfault,c++,memcpy,C++,Memcpy,我试图“打包”一个大的mmap()d文件,如下所示: //numBytes is based on user input data = static_cast<char*>(mmap((caddr_t)0, numBytes, PROT_READ, MAP_SHARED, myFile, 0)); int Sender::Packetize(char* data, int numBytes) { int seqNum = 1; int offset = 0;
mmap()
d文件,如下所示:
//numBytes is based on user input
data = static_cast<char*>(mmap((caddr_t)0, numBytes, PROT_READ, MAP_SHARED, myFile, 0));
int
Sender::Packetize(char* data, int numBytes)
{
int seqNum = 1;
int offset = 0;
size_t totalPacked = 0;
unsigned int length = sizeof(struct sockaddr_in);
bool dataRemaining = true;
while(dataRemaining)
{
//MTU = 1460
size_t payloadSize;
(numBytes > MTU) ? payloadSize = MTU : payloadSize = numBytes;
char* payload = (char*)malloc(payloadSize);
memcpy(payload, data, payloadSize);
Packet pac = {seqNum, 0, payloadSize, payload}; //Basic struct
totalPacked += payloadSize;
cout << "Packed Bytes: " << payloadSize << endl;
cout << "Total Packed: " << totalPacked << endl;
dataMap.insert(pair<int, struct Packet>(seqNum, pac));
if(numBytes > MTU)
{
offset += MTU;
data = &data[offset];
}
else
dataRemaining = false;
numBytes -= MTU;
seqNum++;
}
return 0;
}
但是,如果我尝试缩小一块(100740
),我会得到:
是否存在一些我忽略的基本缺陷,导致我的虚拟机在此处发生故障?您正在泄漏
有效负载内存。未释放内存导致问题
问题
所有内存耗尽后,malloc返回NULL
。
您应该始终检查malloc的返回值,以确保分配成功。
如果您试图将内容复制到空内存中,则会出现segfault
解决方案
在适当的位置使用free
释放内存。
我建议在进入循环之前分配内存的MTU大小,并在循环之后返回。如果MTU是编译时常量,则可以更好地使用静态大小的数组,而不是动态分配它
因为您使用C++,而不是<代码> char *有效载荷=(char *)Maloc(PayLoad Stand);<代码>,您可以从某个STL容器中获取内存以自动释放内存
vector<unsigned char> buf(size);
payload = &buf[0];
向量buf(大小);
有效载荷=&buf[0];
当buf超出范围时,您的内存将被释放。我相信这段代码就是罪魁祸首
offset += MTU;
data = &data[offset];
偏移量从0开始,数据从x开始
- 第一次循环偏移现在是1460,data=data+offset=x+1460
- 下一次循环偏移量现在是2920,data=data+offset=(x+1460)+2920=x+4380
- 下一次循环偏移量现在是4380,data=data+offset=(x+4380)+4380=x+8790
因此,数据
的增长速度超过了应有的速度。这意味着您最终将访问数据范围之外的数据
我建议删除data=&data[offset]代码>零件,只需在memcpy中使用数据+偏移量
。我将使用valgrind
和strace
(或类似工具)的一些组合运行,作为快速检查。(numBytes>MTU)?payloadSize=MTU:payloadSize=numBytes代码>真的应该是payloadSize=(numBytes>MTU)?MTU:numBytes代码>或更好的payLoadSize=std::min(numBytes,MTU)代码>。您的两个示例都有错误-它们之间有什么区别?“VM”?您正在虚拟机上运行此操作?VM=虚拟内存?肯定是内存泄漏,但malloc是否可能在仅2兆字节后就耗尽内存?@ooga我猜,可能是因为Sender::Packetize不是动态内存的唯一使用者。感谢您的建议-我无法立即在此处释放内存(因为其他地方需要它),但作为一个测试,我确实尝试删除它,并收到了相同的SEGFULT。这次您收到了SEGFULT,因为您可能正在通过数据映射访问悬空指针。似乎您没有足够的内存,您需要继续发送数据包并释放一些内存。@MohitJain我不明白情况如何-如果我明确的话lydelete payload
在每次循环之后,我仍然会对故障进行分段(在相同的位置,在相同的字节数之后)。@MrDuk注意,valgrind
或类似的工具可能会帮助您发现这一点。
vector<unsigned char> buf(size);
payload = &buf[0];
offset += MTU;
data = &data[offset];