glibc的MALLOC_CHECK_,M_CHECK_ACTION和mcheck有什么区别?

时间:2013-08-09 18:57:26

标签: debugging glibc heap-corruption

glibc似乎有多种方法可以进行堆检查:

  1. 使用M_CHECK_ACTION参数的mallopt
  2. MALLOC_CHECK_环境变量
  3. mcheck函数系列
  4. 我发现可用的文档令人困惑。在描述mallopt时,manual根本没有列出M_CHECK_ACTION。但是,{em>确实描述了M_CHECK_ACTION。此外,它表示它等同于环境变量MALLOC_CHECK _:

       MALLOC_CHECK_
              This environment variable controls the same parameter as
              mallopt() M_CHECK_ACTION.  If this variable is set to a
              nonzero value, then a special implementation of the memory-
              allocation functions is used.  (This is accomplished using the
              malloc_hook(3) feature.)  This implementation performs
              additional error checking, but is slower than the standard set
              of memory-allocation functions.
    

    glibc手册有一个This mallopt man page的页面,并将它们描述为“堆一致性检查”。本页手册讨论了MALLOC_CHECK _:

      

    使用malloc,realloc和free检查和防范错误的另一种可能性是设置环境变量MALLOC_CHECK_。当设置MALLOC_CHECK_时,使用一种特殊(效率较低)的实现,该实现旨在容忍简单错误,例如使用相同参数进行双重调用,或者单个字节超出(逐个错误)。

    所以mcheck等是MALLOC_CHECK_ / M_CHECK_ACTION的替代品吗?

    此外,如何禁用所有这些超级有用的一致性检查?手册页说将MALLOC_CHECK_(因此M_CHECK_ACTION)设置为0将不会使用“内存分配函数的特殊实现”。但是,glibc手册指出“当设置MALLOC_CHECK_时,使用了一种特殊的(效率较低的)实现。”设置为0的环境变量仍然设置,因此其中一个是错误的。

    我自己的实验(使用mcheck and friends中的示例程序)表明,没有设置MALLOC_CHECK_会产生与MALLOC_CHECK_ = 3相同的行为(在RHEL 6.4上)。 mcheck似乎完全不相关,因为它可以独立设置。

2 个答案:

答案 0 :(得分:2)

有四种不同的一致性检查。以下对应于glibc 2.25。

  1. 各种断言。在构建glibc时确定它们是否处于活动状态。在过去,Debian和下游的断言开启了。 Fedora和下游在过去禁用了它们(但目前的Fedora让它们无法使用)。
  2. 核心malloc实施中的一致性检查不使用断言,但是malloc_printerr。过去,可以使用MALLOC_CHECK_=0(和mallopt)关闭它们。但是,我怀疑malloc_printerr之后的错误恢复在所有情况下都是正确的,所以这不太可行。如果存在堆损坏,程序可能很快就会崩溃。
  3. 相对轻量级的堆缓冲区溢出检测。这由MALLOC_CHECK_=3(或其他非零值)启用。 mallopt无法启用此功能。它是通过增加分配的大小并存储一些填充并在某些地方检查它来实现的。这个堆检查器应该是线程安全的,并且与malloc内部结构紧密耦合。但是,它很少使用,因此很容易出现烦人的错误。
  4. mcheck函数,通过与__malloc_initialize_hook链接从libmcheck.a调用。这与之前的检查完全不同。我认为这个想法是通过拥有一组单独的元数据来验证正确的分配行为(独立于实际的分配器),并且mcheck不依赖于glibc malloc内部,除了{{1} }钩子。但是,它使用这些钩子完全不是线程安全的。我认为今天没有人使用malloc。它只是包括在内,因为还没有人删除它。 (它甚至不需要向后兼容性,因为不能保证检测到所有堆损坏,并且破坏堆的应用程序仍然是完全未定义的,因此无法检测mcheck是否实际执行了其他检查。 )
  5. 除此之外,还有mcheck,可用于检测对未初始化或已释放数据的某些形式的访问。

答案 1 :(得分:0)

设置环境变量

  

MALLOC_CHECK_ = N

与调用

相同
  

mallopt(M_CHECK_ACTION,n)

自glibc 2.3.4起,M_CHECK_ACTION参数的默认值为3.

您可以将n设置为 0

  

忽略错误条件;继续执行(未定义的结果)。