【发布时间】:2014-03-24 16:17:55
【问题描述】:
首先,有一点背景知识,这样你就不会认为我在试图做一些疯狂的事情:
我正在尝试调试由其他人编写的 C 库中的崩溃。崩溃看起来像这样:
TheProgram(44365,0x7fff75996310) malloc: *** error for object 0x7fb8d4b9d440: pointer being freed was not allocated
崩溃发生在我无法运行 valgrind 的系统上,唉。我做的第一件事是将调试打印宏包装在库对 malloc()、calloc()、realloc() 和 free() 的所有调用周围,以便在分配/重新分配内存时看到 printf() 输出/由图书馆释放。从该调试输出来看,导致 free() 崩溃的指针似乎确实是先前在程序中分配的,并且在问题 free() 调用之前它没有被释放:
JJ_CHECK_MALLOC at [fastgr.c : 265] malloc() returned 0x7fb8d4b9d440
[...]
JJ_CHECK_FREE at [dotinit.c : 204] about to call free(0x7fb8d4b9d440)
TheProgram(44365,0x7fff75996310) malloc: *** error for object 0x7fb8d4b9d440: pointer being freed was not allocated
所以大概必须发生的事情是在调用 malloc() 之后和调用 free() 之前的某个地方,堆必须以这样一种方式被破坏,free() 不再认为该指针是有效的.
然后,我需要做的是追踪导致堆损坏的例程。我可以做到这一点的一种方法是在执行路径的各个位置查询指针的有效性,并缩小其状态从“有效堆指针”变为“堆管理器不知道该指针是什么”的范围。但是我知道找出堆管理器是否认为指针是可释放的唯一方法是调用 free(),当程序仍然想使用指针时我显然不能这样做。有什么方法可以调用 free() 使用的 check-if-pointer-is-in-heap 函数,而不实际释放数据?
【问题讨论】:
-
你无法判断一个指针是否有效传递给
free。运行 valgrind 以查明内存错误。 -
[Hack] 你可以查看bookkeeping information,它位于
malloc'd 指针指向的缓冲区之前。 -
一般来说,没有。在某些系统上,可能在分配的第一个字节之前有堆簿记数据或类似的,但这将高度依赖于系统。不过,大多数开发环境都有某种(慢)堆错误检测模式可供您使用。
-
释放指针后可能有助于将指针设置为
NULL。 -
如果你不能运行 valgrind,你基本上需要自己重新实现它来进行这种调试——你可以使用 malloc(就像你所做的那样)在内存并定期检查它们是否已损坏。这可能有助于缩小问题范围,但最终您可能希望检测每个内存写入(这就是 valgrind 所做的)。
标签: c debugging heap-memory