【问题标题】:Is there a way to find out if a pointer is okay to pass to free(), other than by calling free()?除了调用 free() 之外,有没有办法确定指针是否可以传递给 free()?
【发布时间】: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


【解决方案1】:

一般来说:没有。

有“调试堆”围绕分配的块,并带有额外的“栅栏”信息,以帮助检测坏指针错误。如果您尝试释放未通过它们分配的东西,这些将相当可靠地抱怨,因为栅栏将丢失。 (当然,如果您覆盖了缓冲区的末尾并损坏了栅栏,他们也会抱怨。)在代码频繁更改的环境中,我有时会在永久启用这些堆的情况下运行,尽管会降低性能......但是人们希望它们可以在代码交付给客户之前正常关闭。

【讨论】:

  • 确实,我怀疑是这样的系统产生了我所看到的错误消息——但我需要找出的不仅仅是堆损坏的事实,而是发生的时间/地点。
  • 调试堆可以与调试器或核心转储一起使用——或者在代码中记录调用,如果你不能得到更好的东西——以确定故障点的程序状态.在那里,这样做有助于说服 IBM,调试堆值得包含在 C 编译器产品中......
猜你喜欢
  • 2012-12-02
  • 2021-09-12
  • 2012-12-05
  • 2011-06-03
  • 2022-01-11
  • 2020-05-13
  • 2016-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多