1

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

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

在我最终通过所有标题时调用的函数中,我遇到了一个奇怪的错误。

    /*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 megs,我有 4 gigs 的 ram,所以我认为我没有用完或任何东西......所以我不得不得出结论 new 没有分配足够的内存,但为什么?

4

1 回答 1

11
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 不包括在内

于 2009-11-25T20:24:37.473 回答