什么可能导致指针分配中的段错误?
我正在尝试调试 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->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;
I am trying to debug native C code for an Android application, where I am getting the following segfault:
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
The relevant code is:
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;
}
I verify that fi is not NULL, as shown, throwing an Exception which is caught by my Java application. I never see an Exception thrown (which I have tested). So, fi is guaranteed to be non-NULL.
If that is the case, then how can this segfault?
EDIT: FIELD_INFO_NEW() is in fact a macro. This is code that belongs to Wireshark that I am trying to debug, since it keeps crashing my application.
#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;
I don't think I should be checking if fi->hfinfo is valid, right? Because, I think from this code SLAB_ALLOC will allocate (or pull in already existing memory) the proper size for fi. Because, hfinfo is a pointer. Therefore, I'm just trying to give that pointer a value, and that assignment is causing the crash:
/** 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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
空指针只是段错误的一种特殊情况。
segfault
意味着您正在尝试访问未分配给您的进程的内存部分(段)。那么FIELD_INFO_NEW(fi)到底在做什么呢?例如,它是否通过 malloc 分配内存?
我的印象是 fi 未正确初始化。所以基本上你试图在一个恰好被禁止的随机地址分配数据。
(幸运的是,它会引发段错误,因为如果您偶然写入允许的内存区域,则很难找出内存损坏的原因,这可能会在代码执行的后期触发奇怪的副作用。)
Null pointer is only a particular case of segfault.
segfault
means you are trying to access to a portion (segment) of memory that is not allocated to your process.So what exactly FIELD_INFO_NEW(fi) is doing ? Does it allocate memory via malloc for example ?
I got the impression that fi is not correctly initialized. So basically you are trying to assign data at a random address that happens to be forbidden.
(And you are lucky it throws a segfault, because if you were by chance writing to an allowed memory area it would be harder to find out the cause of memory corruption that could trigger strange side effect much later in your code execution.)
fi
指向只读存储器。检查您的 FIELD_INFO_NEW 宏。fi
points to read-only memory. Check your FIELD_INFO_NEW macro.仅仅因为它不为空并不意味着您可以安全地访问它或写入它。它可能指向已释放的内存、只读内存或不属于您的内存。其中任何一个都可能导致分段错误。
Just because it's not null doesn't mean that you can safely access it or write to it. It could be pointing to freed memory, read-only memory or memory that just doesn't belong to you. Either of those could cause a segmentation fault.
仅仅因为
fi
不为 null 并不意味着fi
有效。显然,您的 fi 持有一个无效的指针值,该值指向内存中某个完全伪造的不可写位置。在这种情况下,崩溃与“指针分配”无关。您可以将分配
fi->start
的行放在前面,它很可能会在该分配时崩溃。您的问题肯定出在
FIELD_INFO_NEW
中。Just because
fi
is not null does not mean thatfi
is valid. Apparently, yourfi
holds an invalid pointer value to that points to some completely bogus non-writable location in memory.The crash has nothing to do with "pointer assignment" in this case. You can put the line that assigns
fi->start
first and it will most likely crash at that assignment instead.Your problem is certainly in
FIELD_INFO_NEW
.