一旦位置接近100KB,就会在memcpy上发生段错误

时间:2014-04-30 01:58:52

标签: 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;
    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()期间收到段错误。我注意到它似乎是一个大约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)

是否存在一些我忽略的根本缺陷,导致我的虚拟机出现错误?

2 个答案:

答案 0 :(得分:6)

我相信这段代码是罪魁祸首

        offset += MTU;
        data = &data[offset];

偏移量从0开始,数据从x开始。

  • 第一次循环,循环偏移现在是1460,data = data + offset = x + 1460
  • 下一次环路偏移现在是2920,数据=数据+偏移=(x + 1460)+ 2920 = x + 4380
  • 下一轮循环偏移现在是4380,data = data + offset =(x + 4380)+ 4380 = x + 8790

所以data的增长速度超过预期。这意味着最终您将访问data

的范围之外

我建议删除data = &data[offset];部分,并在memcpy中使用data + offset

答案 1 :(得分:1)

你正在泄露payload记忆。不free内存导致问题。

<强>问题 在所有内存耗尽后,malloc返回NULL。 您应该始终检查malloc的返回值以确保分配成功。 如果您尝试将内容复制到NULL内存中,则会出现段错误。

<强>解决方案 在适当的位置使用free来释放内存。 我建议在进入循环之前分配MTU大小的内存并在循环之后返回它。如果MTU是编译时常量,则可以更好地使用静态大小的数组,而不是动态分配它。

因为您使用的是C ++而不是char* payload = (char*)malloc(payloadSize);,所以您可以从某个STL容器中获取内存以自动释放内存。

vector<unsigned char> buf(size);
payload = &buf[0];

当buf超出范围时,你的记忆将被释放。