【问题标题】:what could cause a segfault in pointer assignment?什么可能导致指针分配中的段错误?
【发布时间】:2011-09-02 19:16:23
【问题描述】:

我正在尝试为 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。

如果是这样的话,那这个segfault怎么会出现呢?


编辑: 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->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; 

【问题讨论】:

标签: c debugging segmentation-fault


【解决方案1】:

空指针只是段错误的一种特殊情况。

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

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

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

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

【讨论】:

  • hmmmm,98% 的代码在 x86 上运行,所以我创建了一个测试用例,并用 valgrind 一遍又一遍地运行它,我根本没有看到任何内存泄漏,更不用说与 FIELD_INFO_NEW() 相关。
  • 您能否将 field_info *fi 初始化为可识别的值,例如 NULL 或 0xDEADBEEF。使用调试器可以在调用宏后检查 fi 的值吗?
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    仅仅因为它不为 null 并不意味着您可以安全地访问或写入它。它可能指向已释放的内存、只读内存或不属于您的内存。其中任何一个都可能导致分段错误。

    【讨论】:

      【解决方案4】:

      fi 不为空并不意味着fi 有效。显然,您的 fi 持有一个无效的指针值,指向内存中某个完全伪造的不可写位置。

      在这种情况下,崩溃与“指针分配”无关。您可以将分配 fi-&gt;start 的行放在首位,它很可能会在该分配处崩溃。

      你的问题肯定出在FIELD_INFO_NEW

      【讨论】:

        猜你喜欢
        • 2021-03-02
        • 1970-01-01
        • 2021-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多