我正试图"打包"一个大的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;
}
我正在处理一个2MB+的文件。当我为numBytes
(5000
)传递一些相对较小的东西时,一切似乎都很顺利。但是,如果我试图传递整个文件(2533431
),我会在memcpy()
期间得到segfault。我注意到它似乎是一个问题,大约100KB:
[.. snip ..]
Packed Bytes: 1460
Total Packed: 99280
Packed Bytes: 1460
Total Packed: 100740
Packed Bytes: 1460
Total Packed: 102200
Segmentation fault (core dumped)
然而,如果我尝试缩小一块(100740
),我会得到:
[.. snip ..]
Packed Bytes: 1460
Total Packed: 16060
Packed Bytes: 1460
Total Packed: 17520
Packed Bytes: 1460
Total Packed: 18980
Segmentation fault (core dumped)
是不是有一些我忽略了的根本缺陷,导致我的虚拟机出现故障?
我相信这段代码是的罪魁祸首
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
的边界之外的内容。
我建议删除data = &data[offset];
部分,只在memcpy中使用data + offset
。
您正在泄漏payload
内存。未对内存进行free
操作会导致问题。
问题在所有内存耗尽后,malloc返回NULL
。您应该始终检查malloc的返回值,以确保分配成功。如果您试图将内容复制到NULL内存中,则会得到一个segfault。
解决方案在适当的位置使用free
释放内存。我建议在进入循环之前分配内存的MTU大小,并在循环之后返回。如果MTU是编译时间常数,您可以更好地使用静态大小的数组,而不是动态分配它
因为您使用的是C++,而不是char* payload = (char*)malloc(payloadSize);
,所以您可以从一些STL容器中获取内存来自动释放内存。
vector<unsigned char> buf(size);
payload = &buf[0];
当buf超出范围时,您的内存将被释放。