一旦位置接近100KB,则在memcpy上执行segfault

segfault on memcpy once location approaches 100KB

本文关键字:memcpy 执行 segfault 则在 位置 接近 100KB      更新时间:2023-10-16

我正试图"打包"一个大的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+的文件。当我为numBytes5000)传递一些相对较小的东西时,一切似乎都很顺利。但是,如果我试图传递整个文件(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超出范围时,您的内存将被释放。