什么可能导致指针分配中的段错误?

时间:2011-09-02 19:16:23

标签: c debugging segmentation-fault

我正在尝试为Android应用程序调试本机C代码,我得到以下段错误:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1640]
0x8463022c in new_field_info (tree=0x7c1a98, hfinfo=0x865b6344, tvb=0xa65100, start=8, item_length=2) at proto.c:3491
3491    proto.c: No such file or directory.
        in proto.c
(gdb) bt
#0  0x8463022c in new_field_info (tree=0x7c1a98, hfinfo=0x865b6344, tvb=0xa65100, start=8, item_length=2) at proto.c:3491
#1  0x846303dc in alloc_field_info (tree=0x7c1a98, hfindex=30607, tvb=0xa65100, start=8, length=0xbeb703b0) at proto.c:3519
#2  0x8462fcdc in proto_tree_add_pi (tree=0x7c1a98, hfindex=30607, tvb=0xa65100, start=8, length=0xbeb703b0, pfi=0xbeb70398) at proto.c:3328

相关代码是:

static field_info *
new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
         const gint start, const gint item_length)
{
  field_info    *fi;

  FIELD_INFO_NEW(fi);

  if(fi == NULL)
    throwDissectorException("proto.c", 3483, "fi==NULL");

  fi->hfinfo = hfinfo;  // THIS IS LINE 3491  <----- SEGFAULT
  fi->start = start;
  fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
  fi->length = item_length;
  fi->tree_type = -1;
  fi->flags = 0;

  ...

  return fi;
}

我验证了fi不是NULL,如图所示,抛出了我的Java应用程序捕获的异常。我从未看到抛出异常(我已经测试过)。所以,fi保证是非NULL的。

如果是这种情况,那么这个段错误怎么办?


编辑:FIELD_INFO_NEW()实际上是一个宏。这是我试图调试的Wireshark的代码,因为它不断崩溃我的应用程序。

#define FIELD_INFO_NEW(fi)          \
  SLAB_ALLOC(fi, field_info)

/* we never free any memory we have allocated, when it is returned to us
   we just store it in the free list until (hopefully) it gets used again
*/
#define SLAB_ALLOC(item, type)          \
  if(!type ## _free_list){        \
    int i;            \
    union type ## slab_item *tmp;     \
    tmp=g_malloc(NITEMS_PER_SLAB*sizeof(*tmp)); \
    for(i=0;i<NITEMS_PER_SLAB;i++){     \
      tmp[i].next_free = type ## _free_list;  \
      type ## _free_list = &tmp[i];   \
    }           \
  }             \
  item = &(type ## _free_list->slab_item);    \
  type ## _free_list = type ## _free_list->next_free;

我认为我不应该检查fi-&gt; hfinfo是否有效,对吧?因为,我认为从这个代码SLAB_ALLOC将分配(或拉入已经存在的内存)适当的fi大小。因为,hfinfo是一个指针。因此,我只是试图给该指针赋值,并且该赋值导致崩溃:

/** Contains the field information for the proto_item. */ 
typedef struct field_info { 
  header_field_info *hfinfo;          /**< pointer to registered field information */ 
  gint         start;           /**< current start of data in field_info.ds_tvb */ 
  gint         length;          /**< current data length of item in field_info.ds_tvb */ 
  gint         appendix_start;  /**< start of appendix data */ 
  gint         appendix_length; /**< length of appendix data */ 
  gint         tree_type;       /**< one of ETT_ or -1 */ 
  item_label_t    *rep;             /**< string for GUI tree */ 
  guint32        flags;           /**< bitfield like FI_GENERATED, ... */ 
  tvbuff_t      *ds_tvb;          /**< data source tvbuff */ 
  fvalue_t       value; 
} field_info; 

4 个答案:

答案 0 :(得分:2)

空指针只是segfault的一个特例。

segfault表示您正在尝试访问未分配给您的流程的部分(段)内存。

那究竟FIELD_INFO_NEW(fi)到底在做什么?它是否通过malloc分配内存,例如?

我的印象是fi未正确初始化。所以基本上你试图在一个恰好被禁止的随机地址上分配数据。

(你很幸运它抛出一个段错误,因为如果你偶然写入允许的内存区域,那么很难找到内存损坏的原因,这可能会在代码执行后期引发奇怪的副作用。 )

答案 1 :(得分:0)

fi指向只读内存。检查您的FIELD_INFO_NEW宏。

答案 2 :(得分:0)

仅仅因为它不是null并不意味着您可以安全地访问它或写入它。它可能指向释放的内存,只读内存或不属于您的内存。这些都可能导致分段错误。

答案 3 :(得分:0)

仅仅因为fi不为空并不意味着fi有效。显然,你的fi持有一个无效的指针值,指向内存中一些完全虚假的不可写位置。

在这种情况下,崩溃与“指针分配”无关。您可以将首先分配fi->start的行放在那里,而很可能会在该分配时崩溃。

您的问题肯定在FIELD_INFO_NEW