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我不明白情况如何-如果我明确的话ly
delete payload
在每次循环之后,我仍然会对故障进行分段(在相同的位置,在相同的字节数之后)。@MrDuk注意,
valgrind
或类似的工具可能会帮助您发现这一点。
vector<unsigned char> buf(size);
payload = &buf[0];
        offset += MTU;
        data = &data[offset];