что может вызвать ошибку при назначении указателя? - PullRequest
1 голос
/ 02 сентября 2011

Я пытаюсь отладить собственный код C для приложения Android, где я получаю следующее сообщение об ошибке:

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; 

Ответы [ 4 ]

2 голосов
/ 02 сентября 2011

Нулевой указатель - это только частный случай сегфоута.

segfault означает, что вы пытаетесь получить доступ к той части (сегменту) памяти, которая не выделена вашему процессу.

Так, что именно FIELD_INFO_NEW (fi) делает? Выделяет ли он память, например, через malloc?

У меня сложилось впечатление, что файл неправильно инициализирован. Таким образом, вы пытаетесь назначить данные по случайному адресу, который запрещен.

(И вам повезло, что он генерирует segfault, потому что если бы вы случайно записали в разрешенную область памяти, было бы сложнее выяснить причину повреждения памяти, которое могло бы вызвать странный побочный эффект намного позже при выполнении вашего кода. ) * +1010 *

0 голосов
/ 02 сентября 2011

То, что fi не равно нулю, не означает, что fi является действительным.Очевидно, ваш fi содержит недопустимое значение указателя, которое указывает на какое-то совершенно поддельное недоступное для записи место в памяти.

В этом случае сбой не имеет ничего общего с «назначением указателя».Вы можете поставить строку, которая присваивает fi->start первой, и, скорее всего, вместо этого при этом назначении произойдет сбой.

Ваша проблема определенно в FIELD_INFO_NEW.

0 голосов
/ 02 сентября 2011

Тот факт, что он не равен нулю, не означает, что вы можете безопасно получить к нему доступ или написать.Это может быть указание на свободную память, постоянную память или память, которая просто не принадлежит вам.Любой из них может вызвать ошибку сегментации.

0 голосов
/ 02 сентября 2011

fi указывает на постоянную память.Проверьте свой макрос FIELD_INFO_NEW.

...