新的没有分配足够的内存?

发布于 2024-08-12 06:46:08 字数 2250 浏览 1 评论 0原文

好吧,我直接从网络上获取数据包并从中提取 TCP 流。

简而言之,这意味着剥离各种标头(例如,eth->IP->TCP->流数据)。

在我最终完成所有标头后调用的函数中,我遇到了一个奇怪的错误。

    /*Meta is a pointer to the IP header, pkt is a pointer to the TCP header*/
    virtual const u_char* processPacket(const u_char* pkt, const u_char* meta) {
        //Extract IP info from meta.
        iphdr* metaHdr = (iphdr*)meta;
        //Form TCP header from the current offset, hdr.
        const tcphdr* hdr = (const tcphdr*)pkt;

        //Do pointer math to figure out the size of the stream data.
        u_int32_t len = ntohs(metaHdr->tot_len) - metaHdr->ihl*4 - hdr->doff*4;
        if(len > 0)
        {
            //Store TCP stream data in a queue, mapped to it's IP source.
            TCPStream* stream = new TCPStream();
            stream->seqNumber = ntohl(hdr->seq);
            stream->streamData = new u_char(len);
            //memcpy(stream->streamData, offset(pkt), len);
            for(u_int32_t i = 0; i < len; i++)
            {
                printf("k%i-%i",len, i); //Used to figure out when the segfault occurs.
                stream->streamData[i] = offset(pkt)[i]; //Offset returns a pointer to the data under the TCP header
            }

            //streams[metaHdr->saddr].push(stream);
        }

        return offset(pkt);
    };

TCP 流只是一个 u_int32_t 和一个 u_char* 指向数据包数据的副本。 所以,当我使用 memcpy 时,它出现了段错误。
显然,要么我的指针无效,要么我搞乱了我的长度。

在此特定数据包的情况下,数据长度为 1380 字节(由 Wireshark 确认),因此 len 计算正确。

好吧,所以我的指针一定搞砸了(但不是 NULL)。我做了以下实验:

stream->streamData[0] = offset(pkt)[0]; //Works
stream->streamData[0] = offset(pkt)[len]; //Works, odd.
stream->streamData[len] = offset(pkt)[0]; //Fails, scary
stream->streamData[len] = offset(pkt)[len]; //Fails

因此,当对streamData(具体来说是索引1236)解除引用太远时,我会出现段错误! 但是streamData被实例化为:

stream->streamData = new u_char(len); 

我在i=0处开始迭代streamData,所以我不会跳过一堆数据。 StreamData 是 u_char* ,而 offset(pkt)u_char* 所以我不会弄乱我的类型。

在成功迭代 3000 多个其他数据包后,此操作在特定数据包处失败。转储文件有 27 兆,我有 4 GB 内存,所以我不认为我用完了或者什么......所以我被迫得出结论 new 没有分配足够的内存,但为什么?

Well, I'm taking packets straight off the wire and extracting TCP streams from them.

In the short, this means stripping off the various headers (eg, eth->IP->TCP->stream data).

In the function that is called when I've finally gotten through all the headers, I am experiencing a strange error.

    /*Meta is a pointer to the IP header, pkt is a pointer to the TCP header*/
    virtual const u_char* processPacket(const u_char* pkt, const u_char* meta) {
        //Extract IP info from meta.
        iphdr* metaHdr = (iphdr*)meta;
        //Form TCP header from the current offset, hdr.
        const tcphdr* hdr = (const tcphdr*)pkt;

        //Do pointer math to figure out the size of the stream data.
        u_int32_t len = ntohs(metaHdr->tot_len) - metaHdr->ihl*4 - hdr->doff*4;
        if(len > 0)
        {
            //Store TCP stream data in a queue, mapped to it's IP source.
            TCPStream* stream = new TCPStream();
            stream->seqNumber = ntohl(hdr->seq);
            stream->streamData = new u_char(len);
            //memcpy(stream->streamData, offset(pkt), len);
            for(u_int32_t i = 0; i < len; i++)
            {
                printf("k%i-%i",len, i); //Used to figure out when the segfault occurs.
                stream->streamData[i] = offset(pkt)[i]; //Offset returns a pointer to the data under the TCP header
            }

            //streams[metaHdr->saddr].push(stream);
        }

        return offset(pkt);
    };

TCP stream is simply a u_int32_t and a u_char* pointing to a copy of the packet's data.
So, when I was using memcpy it segfaulted.
Obviously, either my pointers were invalid, or I was messing up my length.

In this particular packet's case, the length of the data is 1380 bytes (confirmed by Wireshark), so len is correctly computed.

Ok, so I must have my pointers messed up (but not NULL). I did the following experiment:

stream->streamData[0] = offset(pkt)[0]; //Works
stream->streamData[0] = offset(pkt)[len]; //Works, odd.
stream->streamData[len] = offset(pkt)[0]; //Fails, scary
stream->streamData[len] = offset(pkt)[len]; //Fails

So, I segfault when dereferencing too far into streamData (index 1236 to be specific)!
But streamData is instantiated as:

stream->streamData = new u_char(len); 

I start iterating through streamData at i=0, so I'm not skipping a bunch of my data.
streamData is u_char* and offset(pkt) is u_char* so I'm not messing up my types.

This fails at a particular packet, after successfully iterating through 3000+ other packets. The dump file is 27 megs, and I've got 4 gigs of ram, so I don't think I'm running out or anything... So I'm forced to conclude that new is not allocating enough memory, but why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月棠 2024-08-19 06:46:08
stream->streamData = new u_char(len);

这会分配一个字符,初始化为len

要分配数组,请使用:

stream->streamData = new u_char[len];

并且无论在何处释放它:

delete [] stream->streamData;

编辑:

stream->streamData[len] = offset(pkt)[0]; //Fails, scary

即使数组已正确分配,这也将是未定义的行为。要访问的有效索引为 0 到 len 不包含

stream->streamData = new u_char(len);

This allocates a single character, intialized to len.

To allocate an array, use:

stream->streamData = new u_char[len];

And where-ever you deallocate it:

delete [] stream->streamData;

Edit:

stream->streamData[len] = offset(pkt)[0]; //Fails, scary

That would be undefined behavior even if the array was allocated correctly. Valid indexes to access are 0 to len not inclusive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文