段错误代码的可能原因是什么?

时间:2012-12-02 06:11:25

标签: c++ linux memory segmentation-fault

我最近遇到了段错误问题,在调用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)?有没有办法告诉错误代码可能的原因?

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

1 个答案:

答案 0 :(得分:1)

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

这导致在SIGSEGV上接收delete的最常见原因:双重释放(试图释放已经被释放的指针)。但是,任何堆损坏(例如,通过双重释放其他东西或其他地方的缓冲区溢出/越界错误)都可能是原因。

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

valgrind在其内存模型中是详尽无遗的,并且在启用适当数量的检查后,几乎肯定会找到问题的根源。

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

请注意,在空指针上使用C ++ LD_PRELOAD在技术上不是问题,所以你可以从你的清单中划掉那个(因为我猜你可能已经有了,通过修改代码来明确检查)在删除之前)。

更多细节:

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

换句话说,内核错误代码在常见的调试方案中确实没有多大帮助。

我假设您在delete下运行程序,并在崩溃前设置断点几行,以观察被删除指针的值以及周围状态的其余部分。

编辑:

当我显然是gdb时,删除了错误的-g2引用。为您添加了进一步的诊断问题和解释。