glibc的MALLOC_CHECK_、M_CHECK_ACTION和mcheck之间的区别是什么?

时间:2021-01-14 07:02:32

glibc seems to have more than one way of doing some heap checking:

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

  1. mallopt with the M_CHECK_ACTION parameter
  2. 使用M_CHECK_ACTION参数进行mallopt
  3. the MALLOC_CHECK_ environment variable
  4. MALLOC_CHECK_环境变量
  5. the mcheck family of functions
  6. 功能的mcheck系列。

I find the available documentation to be confusing. The manual doesn't list M_CHECK_ACTION at all when describing mallopt. This mallopt man page, however, does describe M_CHECK_ACTION. Additionally, it says it's equivalent to the environment variable MALLOC_CHECK_:

我发现可用的文档令人困惑。手册在描述mallopt时没有列出M_CHECK_ACTION。不过,这个mallopt man页面确实描述了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.

The glibc manual has a page for mcheck and friends and describes them as "heap consistency checking". It is on this page that the manual discusses MALLOC_CHECK_:

glibc手册有一个用于mcheck和friends的页面,并将其描述为“堆一致性检查”。在这个页面上,手册讨论了MALLOC_CHECK_:

Another possibility to check for and guard against bugs in the use of malloc, realloc and free is to set the environment variable MALLOC_CHECK_. When MALLOC_CHECK_ is set, a special (less efficient) implementation is used which is designed to be tolerant against simple errors, such as double calls of free with the same argument, or overruns of a single byte (off-by-one bugs).

另一种检查和防止malloc、realloc和free使用bug的可能性是设置环境变量MALLOC_CHECK_。当设置MALLOC_CHECK_时,将使用一种特殊的(效率较低的)实现,这种实现设计用于容忍简单的错误,例如使用相同的参数进行两次*调用,或者对单个字节(一个字节的错误)进行越界。

So mcheck et al is an alternative to MALLOC_CHECK_/M_CHECK_ACTION?

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

Furthermore, how does one disable all this super-helpful consistency checking? The man page says setting MALLOC_CHECK_ (and therefore M_CHECK_ACTION) to 0 will not use "a special implementation of the memory-allocation functions." The glibc manual, however, states that "When MALLOC_CHECK_ is set, a special (less efficient) implementation is used." An environment variable set to 0 is still set, so one of these is wrong.

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

My own experiments (using the example program from this mcheck man page) show that not having MALLOC_CHECK_ set at all results in the same behavior as MALLOC_CHECK_=3 (on RHEL 6.4). And mcheck seems completely unrelated, as it can be set independently.

我自己的实验(使用来自这个mcheck man页面的示例程序)表明,不设置MALLOC_CHECK_ set会导致与malloc_check_= 3相同的行为(在RHEL 6.4上)。而mcheck看起来完全不相关,因为它可以独立设置。

2 个解决方案

#1


1  

There are four different consistency checks. The following corresponds to glibc 2.25.

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

  1. Various asserts. Whether they are active is determined when glibc is built. In the past, Debian and downstreams left asserts switched on. Fedora and downstreams disabled them in the past (but current Fedora leaves them on).
  2. 各种各样的断言。它们是否活跃取决于构建glibc的时间。在过去,Debian和downstreams left assert打开。Fedora和downstreams在过去禁用了它们(但是当前的Fedora保留了它们)。
  3. Consistency checks in the core malloc implementation which do not use asserts, but malloc_printerr. In the past, they could be switched off using MALLOC_CHECK_=0 (and mallopt). However, the I doubt that the error recovery after malloc_printerr is correct in all cases, so this is unlikely to work. And if there is heap corruption, the program might crash soon anyway.
  4. 在不使用断言而是使用malloc_printerr的核心malloc实现中进行一致性检查。在过去,可以使用MALLOC_CHECK_=0(和mallopt)关闭它们。然而,我怀疑malloc_printerr之后的错误恢复在所有情况下都是正确的,因此这不太可能奏效。如果存在堆损坏,程序可能很快就会崩溃。
  5. Relatively lightweight heap buffer overflow detection. This is enabled by MALLOC_CHECK_=3 (or another non-zero value). This cannot be switched on by mallopt. It is implemented by increasing the size of allocations and storing some padding and checking it in some places. This heap checker should be thread-safe, and it is tightly coupled with malloc internals. However, it is rarely used, so there could easily be annoying bugs.
  6. 相对轻量级的堆缓冲区溢出检测。这是由MALLOC_CHECK_=3(或另一个非零值)启用的。这不能由mallopt打开。它通过增加分配的大小和存储一些填充并在一些地方检查它来实现。这个堆检查器应该是线程安全的,并且它与malloc内部构件紧密耦合。但是,它很少被使用,因此很容易出现令人讨厌的bug。
  7. The mcheck function, called from __malloc_initialize_hook by linking with libmcheck.a. This is completely different from the previous checks. I think the idea is to verify correct allocation behavior by having a separate set of metadata (independent of the actual allocator), and mcheck does not depend on the glibc malloc internals except for the malloc hooks. However, its use of these hooks completely not thread safe. I don't think anyone uses mcheck today. It is just included because no one has removed it yet. (It is not even needed for backwards compatibility because there is no guarantee that all heap corruption is detected, and applications which corrupt the heap are still completely undefined, so there is no way to detect whether mcheck actually performs additional checks.)
  8. 通过连接libmchecka,从__malloc_initialize_hook调用mcheck函数。这与以前的检查完全不同。我认为这个想法是通过拥有一组独立的元数据(独立于实际的分配器)来验证正确的分配行为,mcheck不依赖glibc malloc内部,除了malloc钩子。然而,它使用这些钩子完全不安全。我认为今天没有人使用mcheck。只是因为还没有人把它移除,所以才包含了它。(它甚至不需要向后兼容,因为不能保证检测到所有堆损坏,而且破坏堆的应用程序仍然完全没有定义,因此无法检测mcheck是否真的执行额外的检查。)

In addition to that, there is also MALLOC_PERTURB_, which can be used to detect some forms of access to uninitialized or freed data.

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

#2


0  

setting the environment variable

设置环境变量

MALLOC_CHECK_=n

MALLOC_CHECK_ = n

is the same as calling

和打电话一样吗

mallopt(M_CHECK_ACTION, n)

mallopt(M_CHECK_ACTION n)

Since glibc 2.3.4, the default value for the M_CHECK_ACTION parameter is 3.

由于glibc 2.3.4, M_CHECK_ACTION参数的默认值为3。

You can set n to 0

你可以把n设为0

Ignore error conditions; continue execution (with undefined results).

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

#1


1  

There are four different consistency checks. The following corresponds to glibc 2.25.

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

  1. Various asserts. Whether they are active is determined when glibc is built. In the past, Debian and downstreams left asserts switched on. Fedora and downstreams disabled them in the past (but current Fedora leaves them on).
  2. 各种各样的断言。它们是否活跃取决于构建glibc的时间。在过去,Debian和downstreams left assert打开。Fedora和downstreams在过去禁用了它们(但是当前的Fedora保留了它们)。
  3. Consistency checks in the core malloc implementation which do not use asserts, but malloc_printerr. In the past, they could be switched off using MALLOC_CHECK_=0 (and mallopt). However, the I doubt that the error recovery after malloc_printerr is correct in all cases, so this is unlikely to work. And if there is heap corruption, the program might crash soon anyway.
  4. 在不使用断言而是使用malloc_printerr的核心malloc实现中进行一致性检查。在过去,可以使用MALLOC_CHECK_=0(和mallopt)关闭它们。然而,我怀疑malloc_printerr之后的错误恢复在所有情况下都是正确的,因此这不太可能奏效。如果存在堆损坏,程序可能很快就会崩溃。
  5. Relatively lightweight heap buffer overflow detection. This is enabled by MALLOC_CHECK_=3 (or another non-zero value). This cannot be switched on by mallopt. It is implemented by increasing the size of allocations and storing some padding and checking it in some places. This heap checker should be thread-safe, and it is tightly coupled with malloc internals. However, it is rarely used, so there could easily be annoying bugs.
  6. 相对轻量级的堆缓冲区溢出检测。这是由MALLOC_CHECK_=3(或另一个非零值)启用的。这不能由mallopt打开。它通过增加分配的大小和存储一些填充并在一些地方检查它来实现。这个堆检查器应该是线程安全的,并且它与malloc内部构件紧密耦合。但是,它很少被使用,因此很容易出现令人讨厌的bug。
  7. The mcheck function, called from __malloc_initialize_hook by linking with libmcheck.a. This is completely different from the previous checks. I think the idea is to verify correct allocation behavior by having a separate set of metadata (independent of the actual allocator), and mcheck does not depend on the glibc malloc internals except for the malloc hooks. However, its use of these hooks completely not thread safe. I don't think anyone uses mcheck today. It is just included because no one has removed it yet. (It is not even needed for backwards compatibility because there is no guarantee that all heap corruption is detected, and applications which corrupt the heap are still completely undefined, so there is no way to detect whether mcheck actually performs additional checks.)
  8. 通过连接libmchecka,从__malloc_initialize_hook调用mcheck函数。这与以前的检查完全不同。我认为这个想法是通过拥有一组独立的元数据(独立于实际的分配器)来验证正确的分配行为,mcheck不依赖glibc malloc内部,除了malloc钩子。然而,它使用这些钩子完全不安全。我认为今天没有人使用mcheck。只是因为还没有人把它移除,所以才包含了它。(它甚至不需要向后兼容,因为不能保证检测到所有堆损坏,而且破坏堆的应用程序仍然完全没有定义,因此无法检测mcheck是否真的执行额外的检查。)

In addition to that, there is also MALLOC_PERTURB_, which can be used to detect some forms of access to uninitialized or freed data.

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

#2


0  

setting the environment variable

设置环境变量

MALLOC_CHECK_=n

MALLOC_CHECK_ = n

is the same as calling

和打电话一样吗

mallopt(M_CHECK_ACTION, n)

mallopt(M_CHECK_ACTION n)

Since glibc 2.3.4, the default value for the M_CHECK_ACTION parameter is 3.

由于glibc 2.3.4, M_CHECK_ACTION参数的默认值为3。

You can set n to 0

你可以把n设为0

Ignore error conditions; continue execution (with undefined results).

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