【问题标题】:What is the difference between glibc's MALLOC_CHECK_, M_CHECK_ACTION, and mcheck?glibc 的 MALLOC_CHECK_、M_CHECK_ACTION 和 mcheck 有什么区别?
【发布时间】:2013-08-11 19:15:12
【问题描述】:

glibc 似乎有不止一种方法来做一些堆检查:

  1. mallopt 与 M_CHECK_ACTION 参数
  2. MALLOC_CHECK_ 环境变量
  3. mcheck 系列函数

我发现可用的文档令人困惑。 manual 在描述 mallopt 时根本没有列出 M_CHECK_ACTION。 This mallopt man page,然而,确实描述了 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 手册有一个mcheck and friends 的页面,并将它们描述为“堆一致性检查”。手册在此页面上讨论了 MALLOC_CHECK_:

在使用 malloc、realloc 和 free 时检查和防范错误的另一种可能性是设置环境变量 MALLOC_CHECK_。当设置 MALLOC_CHECK_ 时,将使用一种特殊的(效率较低的)实现,该实现旨在容忍简单的错误,例如使用相同参数的两次 free 调用,或单个字节的溢出(off-by-one 错误)。

所以 mcheck et al 是 MALLOC_CHECK_/M_CHECK_ACTION 的替代品?

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

我自己的实验(使用来自this mcheck man page 的示例程序)表明,完全没有设置 MALLOC_CHECK_ 会导致与 MALLOC_CHECK_=3 相同的行为(在 RHEL 6.4 上)。而mcheck似乎完全无关,因为它可以独立设置。

【问题讨论】:

    标签: debugging glibc heap-corruption


    【解决方案1】:

    有四种不同的一致性检查。以下对应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 函数,通过与libmcheck.a 链接从__malloc_initialize_hook 调用。这与之前的检查完全不同。我认为这个想法是通过拥有一组单独的元数据(独立于实际分配器)来验证正确的分配行为,并且mcheck 不依赖于glibc malloc 内部,除了malloc 挂钩。然而,它对这些钩子的使用完全不是线程安全的。我认为今天没有人使用mcheck。它只是被包括在内,因为还没有人删除它。 (向后兼容甚至不需要它,因为无法保证检测到所有堆损坏,并且损坏堆的应用程序仍然完全未定义,因此无法检测mcheck 是否真的执行了额外的检查。)

    除此之外,还有MALLOC_PERTURB_,可用于检测对未初始化或已释放数据的某些形式的访问。

    【讨论】:

      【解决方案2】:

      设置环境变量

      MALLOC_CHECK_=n

      和调用一样

      mallopt(M_CHECK_ACTION, n)

      从 glibc 2.3.4 开始,M_CHECK_ACTION 参数的默认值为 3。

      你可以将n设置为0

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-26
        • 1970-01-01
        • 2010-10-02
        • 2011-12-12
        • 2010-09-16
        • 2012-03-14
        • 2012-02-06
        • 2011-02-25
        相关资源
        最近更新 更多