跳转到内容

Linux 应用程序调试技术/堆损坏

来自 Wikibooks,开放书籍,为开放世界

Electric Fence

[编辑 | 编辑源代码]

Electric Fence 仍然是处理堆损坏的参考工具,即使它已经有一段时间没有维护了。RedHat 发布了一个可以作为中间库使用的版本。

缺点:可能不适用于使用mmap()分配内存的代码。

Duma 是 Electric Fence 的一个分支。

glibc 内置

[编辑 | 编辑源代码]

man (3) malloc: 最新的 Linux libc 版本(高于 5.4.23)和 GNU libc(2.x)包含一个可通过环境变量调整的 malloc 实现。当MALLOC_CHECK_被设置时,会使用一个特殊的(效率较低)实现,该实现旨在容忍简单的错误,例如使用相同参数对 free() 进行两次调用,或者越界一个字节(越界错误)。但是,并非所有此类错误都能得到保护,可能会导致内存泄漏。如果MALLOC_CHECK_被设置为 0,则会静默忽略任何检测到的堆损坏,不会生成错误消息;如果设置为 1,则会将错误消息打印到 stderr,但程序不会中止;如果设置为 2,则会立即调用 abort(),但不会生成错误消息;如果设置为 3,则会将错误消息打印到 stderr,并中止程序。这很有用,因为否则可能会在很晚的时候发生崩溃,而实际的错误原因很难追查。

C++ stdlib 内置

[编辑 | 编辑源代码]

使用以下命令进行编译-D_GLIBCXX_DEBUG- 它会在 C++ 标准库中开启调试检查。

AddressSanitizer

[编辑 | 编辑源代码]

一个通过以下命令实现的快速内存错误检测器-fsanitize=address, 使用最新的 gcc(从 4.8 开始)或 clang(从 3.1 开始)。内存访问指令会被检测到堆、栈和全局缓冲区溢出以及使用后释放错误。为了获得更友好的堆栈跟踪,请使用 -fno-omit-frame-pointer。AddressSanitizer 可用于 IA-32/x86-64/x32/PowerPC/PowerPC64 GNU/Linux 和 x86-64 Darwin。

从 gcc 4.9 及更高版本开始,您可以使用 ubsan 编译器 进行边界检查。

gdb heisenbugs

[编辑 | 编辑源代码]

使用 GDB 时不会出现,但未使用 GDB 时出现的与内存相关的错误通常是由 GDB 禁用 ASLR 引起的。这通常对调试会话的可重复性很有用,但确实会使地址空间布局过于可预测,从而无法重现错误。尝试使用 GDB 命令 “set disable-randomization off”(不带引号)来撤销此行为,从而在正常的随机环境中启动程序。

华夏公益教科书