仅在不使用调试器时出现段错误
Posted
技术标签:
【中文标题】仅在不使用调试器时出现段错误【英文标题】:segfault only when NOT using debugger 【发布时间】:2011-06-05 10:31:05 【问题描述】:我有一个多线程 C 程序,它始终在程序的特定点生成分段错误。当我用 gdb 运行它时,没有显示错误。你能想到为什么只有在不使用调试器时才会发生故障的原因吗?不能用它来发现问题,真是烦人!
【问题讨论】:
这种错误被称为"Heisenbug",可能有很多原因。 错误是否与窗口管理和/或User32.dll有关? 我遇到了这样的问题,我的程序只在 GDB 中崩溃了。问题是当我运行我的程序时,一个未初始化的类成员变量的值仍然为 0,但是当我在 GDB 中运行它时,它有一些巨大的值,当我将它用作数组索引时会出现段错误。 与 Windows 无关 - 我使用的是 Linux 2.6.32-24-generic #43-Ubuntu。 您是否尝试过安排核心转储?在调试器外部启动程序之前运行ulimit -c unlimited
,然后在转储内核之后运行gdb myprogram core
。然后 gdb 将能够对您的段错误进行事后分析。
【参考方案1】:
经典Heisenbug。来自***:
时间也可能是海森虫的一个因素。与正常执行相比,在调试器的控制下执行程序可以改变程序的执行时间。当程序被调试器中的单步源代码行减慢时,可能无法重现时间敏感的错误,例如竞态条件。当行为涉及与不受调试器控制的实体交互时尤其如此,例如在两台机器之间调试网络数据包处理并且只有一台机器处于调试器控制之下时。
调试器可能会改变时间,并隐藏竞争条件。
在 Linux 上,GDB 还禁用地址空间随机化,并且您的崩溃可能特定于地址空间布局。试试(gdb) set disable-randomization off
。
最后,ulimit -c unlimited
和事后调试(Robie 已经建议)可能会起作用。
【讨论】:
'set disable-randomization off' 为我解决了类似的问题!【参考方案2】:也许在使用gdb
时,内存被映射到您的溢出/不足流不会践踏内存而导致崩溃的位置。或者它可能是不再被绊倒的竞争条件。虽然这听起来不直观,但您应该高兴您的程序足够好,足以让您崩溃。
一些建议
-
试试免费的静态代码分析器
cppcheck
试试 malloc() 调试器,例如
libefence
尝试通过valgrind 运行它
【讨论】:
【参考方案3】:通过调试它,你正在改变它运行的环境。听起来你正在处理某种竞争条件,通过调试它,事情的安排略有不同,所以你不会遇到问题。那,或者事情以稍微不同的方式存储,所以它不会发生。你能在代码中加入一些调试输出来帮助找出问题吗?这可能影响较小,并且可以让您找到您的问题。
【讨论】:
【参考方案4】:我以前完全有过这个问题!这是一个竞争条件,当我使用调试器单步执行代码时,我所在的线程速度很慢,无法触发竞争条件。相当可怕。
【讨论】:
【参考方案5】:如果您使用的是gcc
,请尝试使用-Wall
选项来获取所有警告。如果您使用 Eclipse 之类的 IDE,它会自动执行此操作。
【讨论】:
以上是关于仅在不使用调试器时出现段错误的主要内容,如果未能解决你的问题,请参考以下文章
FBSOpenApplicationServiceErrorDomain
React Native iOS 8.1 应用程序在访问新视图时崩溃 - 仅在不使用调试器时