1

我最近遇到一个段错误问题,在调用 delete 方法时被命中。我已经深入检查了代码,并消除了删除空指针、多次删除或越界(分配的内存足够大,可以容纳之后写入的内容)的可能性。这个问题可以重现,每次它在同一个地方出现段错误。

我不知道可能导致此问题的原因。我想知道是否有可能从我得到的错误代码中得到一些线索,例如:- segfault at xxxxxxxxxxxxxx rip xxxxxxxxxxxxxx rsp xxxxxxxxxxxxxx error 4

我在网上搜索了很长时间,只从 stackoverflow 获得有用的以下信息:-

“错误代码只是页面错误的架构错误代码,似乎是特定于架构的。它们通常记录在内核源代码的 arch/*/mm/fault.c 中。我的 Linux/arch/i386/mm/ 副本fault.c 对 error_code 的定义如下:

bit 0 == 0 means no page found, 1 means protection fault
bit 1 == 0 means read, 1 means write
bit 2 == 0 means kernel, 1 means user-mode

"

这是我的问题:- 错误代码 4 的可能原因是什么(我的平台是 RHEL5 64 位,x86_64)?有没有办法从错误代码中判断可能的原因?

任何其他有关如何诊断此类问题的建议也值得赞赏!

4

1 回答 1

1

鉴于arch/i386/mm/fault.c您提供的文档,错误代码 4 对应于“未找到页面的用户模式读取”。代码 4 = 100 的二进制表示,其中第 2 位是最高有效位(最左边)。

这与在 a 上接收 a 的最常见原因相吻合SIGSEGVdeletea double-free(尝试释放已被释放的指针)。但是,任何堆损坏(例如,通过双重释放其他东西或其他地方的缓冲区溢出/越界错误)都可能是原因。

valgrind尝试在内存分配例程的调试版本下运行代码(使用调试符号编译)或使用调试版本运行(MALLOC_CHECK_在运行二进制文件之前在环境中设置为 1 或 2),两种不同的方法都试图捕获这些错误并报告制作完成后立即发送给您。

valgrind它的内存模型是详尽无遗的,并且在打开适当数量的检查后,几乎可以肯定地找到问题的根源。

MALLOC_CHECK_是 glibc 内部的,并且与大多数其他不是的内存调试工具一样valgrind,它只能捕获某些类型的相对常见的错误并在某些情况下检测堆损坏。还有许多其他工具MALLOC_CHECK_(例如 Electric Fence),但前者已经内置到您的 C 库中,而其他工具充其量要求它们的库(主要包含mallocfree覆盖)是动态的在 C 库之前使用LD_PRELOAD.

请注意,delete在空指针上使用 C++ 在技术上不是问题,因此您可以从清单中划掉那个(我猜您可能已经拥有,通过修改代码以在删除之前显式检查)。

更多细节:

与“未找到页面的用户模式读取”相对应的错误代码意味着指向内存的指针(一些 32/64 位数字指代虚拟地址空间中的某处)被取消引用(即,一些代码试图读取指针持有的虚拟内存地址处的值),但内核页表表明虚拟地址指的是[内存]页面,该页面要么未映射到您的进程中,要么已从您的进程中取消映射,因为该指针有效. 除了想象这种情况发生的明显方式之外,它还可能由于堆损坏(其中包含幕后的各种簿记信息)而间接发生:例如,可以对传递给的值进行指针运算delete使用堆内部的另一个较早损坏的指针,然后导致指针中的无效值,只是等待代码尝试使用它。

换句话说,内核错误代码在常见的调试场景中对你帮助不大。

我假设你已经运行了你的程序,gdb并且只是在崩溃前几行设置了一个断点,以观察被删除的指针的值和周围状态的其余部分。

编辑:

-g2当我明显的意思时删除了错误的参考MALLOC_CHECK_。为您添加了进一步的诊断问题和解释。

于 2012-12-02T06:23:31.850 回答