【问题标题】:thread1: EXC_BAD_ACCESS (code=1, address=0x0) with pcap_nextthread1: EXC_BAD_ACCESS (code=1, address=0x0) with pcap_next
【发布时间】:2014-05-21 17:46:03
【问题描述】:

我正在尝试使用pcap_next,但我的程序停在这一行:

packet = pcap_next([self pcap_socket], hdr);

出现错误:

thread1: EXC_BAD_ACCESS (code=1, address=0x0)

这是我的代码:

-(const u_char*)readOnPcapDescriptor
{
    if([self pcap_is_open]) {
        struct pcap_pkthdr *hdr = NULL;
        const u_char *packet;

        // read for the next packet
        packet = pcap_next([self pcap_socket], hdr);

        if(packet==NULL)
            return NULL;
        else
            return packet;
    }

    printf("NOK\nOpen descriptor First!\n\n");
    exit(1);
}

我不明白我的错误在哪里。 pcap_t 描述符在此之前是打开的:

pcap_t * open_socket = pcap_open_live(if_name,BUFSIZ,1,1,pcap_errbuf);

并影响到一个实例变量:

[self setPcap_socket:open_socket];

【问题讨论】:

  • 你确认pcap_open_live实际上返回了非NULL吗?
  • 是的,我使用 pcap 描述符发送一个带有 pcap_inject 的数据包,然后开始使用 pcap_next 读取

标签: objective-c exc-bad-access pcap


【解决方案1】:

pcap_next documentation 并不表示pcap_pkthdr 参数允许为 NULL。尝试将有效指针传递给 pcap_pkthdr 结构:

struct pcap_pkthdr hdr = {0};
packet = pcap_next([self pcap_socket], &hdr);

【讨论】:

    【解决方案2】:

    pcap_next() 的文档告诉您“h 指向的 pcap_pkthdr 结构中填充了数据包的适当值。”

    在您的示例中,h 被称为 hdr,您可以这样初始化它:

    struct pcap_pkthdr *hdr = NULL;
    

    换句话说,pcap_next() 尝试访问NULL 的地址,这正是错误消息中所述的内容。

    【讨论】:

      【解决方案3】:

      我只能读取 2 个数据包

      引用pcap_next() 手册页:

         pcap_next() returns a pointer  to  the  packet  data  on  success,  and
         returns  NULL  if  an  error occured, or if no packets were read from a
         live capture (if, for example, they were discarded because they  didn't
         pass the packet filter, or if, on platforms that support a read timeout
         that starts before any packets arrive, the timeout expires  before  any
         packets  arrive, or if the file descriptor for the capture device is in
         non-blocking mode and no packets were available to be read), or  if  no
         more  packets are available in a ``savefile.''  Unfortunately, there is
         no way to determine whether an error occured or not.
      

      这里重要的是“如果......或者如果没有从实时捕获中读取数据包(......或者如果在支持在任何数据包到达之前开始的读取超时的平台上,超时到期),则返回 NULL在任何数据包到达之前..."

      BSD 风格的操作系统,例如 OS X 和 iOS,支持在任何数据包到达之前开始的读取超时,因此如果没有任何数据包现在,您可能会返回 NULL。这是否意味着永远不会有任何数据包;你必须继续循环。

      pcap_next()不区分错误和超时;正如手册页所说,“不幸的是,无法确定是否发生错误。”。因此,它不是,也从来不是一个非常好的例程。

      如果您不想使用接受回调的例程,例如pcap_dispatch()pcap_loop(),我建议您使用pcap_next_ex(),它可以区分错误和“无数据包”在超时间隔内到达”。

      【讨论】:

      • 这正是我的问题“在任何数据包到达之前读取超时开始”。
      • 我将 pcap_open_live 中的 to_ms 从 1 更改为 100。现在,我收到了我想要的一切。其实一开始我用的是pcap_next_ex,也收到了2个包。我认为问题来自非阻塞模式。这就是我尝试使用 pcap_next 的原因。现在,我将代码改回 pcap_next_ex,to_ms 为 100,它可以工作。谢谢
      • "我以为问题出在非阻塞模式。"仅当您使用pcap_setnonblock() 开启非阻塞模式时才会出现问题;默认情况下它是关闭的。非阻塞模式不是使用pcap_next()的理由; pcap_next_ex()pcap_loop()pcap_dispatch() 都比 pcap_next() 更好地处理非阻塞模式。
      • "我将 pcap_open_live 中的 to_ms 从 1 更改为 100。现在,我收到了我想要的一切。"除非你不这样做。 1 毫秒是一个小超时 - tcpdump 使用 1 秒,Wireshark 使用 250 毫秒 - 所以更大的超时可能是您想要的。但是,如果流量变慢,您仍将面临pcap_next() 返回 NULL 的风险,因此您仍应始终使用pcap_next_ex() 并且不要在超时时停止捕获。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-19
      • 1970-01-01
      • 2013-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多