【问题标题】: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 将能够对您的段错误进行事后分析。

标签: c debugging gdb segmentation-fault


【解决方案1】:

经典Heisenbug。来自维基百科:

时间也可能是海森虫的一个因素。与正常执行相比,在调试器的控制下执行程序可以改变程序的执行时间。当程序被调试器中的单步源代码行减慢时,可能无法重现时间敏感的错误,例如竞态条件。当行为涉及与不受调试器控制的实体交互时尤其如此,例如在两台机器之间调试网络数据包处理并且只有一台机器处于调试器控制之下时。

调试器可能会改变时间,并隐藏竞争条件。

在 Linux 上,GDB 还禁用地址空间随机化,并且您的崩溃可能特定于地址空间布局。试试(gdb) set disable-randomization off

最后,ulimit -c unlimited 和事后调试(Robie 已经建议)可能会起作用。

【讨论】:

  • 'set disable-randomization off' 为我解决了类似的问题!
【解决方案2】:

也许在使用gdb 时,内存被映射到您的溢出/不足流不会践踏内存而导致崩溃的位置。或者它可能是不再被绊倒的竞争条件。虽然这听起来不直观,但您应该高兴您的程序足够好,足以让您崩溃。

一些建议

  1. 试试免费的静态代码分析器 cppcheck
  2. 试试 malloc() 调试器,例如 libefence
  3. 尝试通过valgrind 运行它

【讨论】:

    【解决方案3】:

    通过调试它,你正在改变它运行的环境。听起来你正在处理某种竞争条件,通过调试它,事情的安排略有不同,所以你不会遇到问题。那,或者事情以稍微不同的方式存储,所以它不会发生。你能在代码中加入一些调试输出来帮助找出问题吗?这可能影响较小,并且可以让您找到您的问题。

    【讨论】:

      【解决方案4】:

      我以前完全有过这个问题!这是一个竞争条件,当我使用调试器单步执行代码时,我所在的线程速度很慢,无法触发竞争条件。相当可怕。

      【讨论】:

        【解决方案5】:

        如果您使用的是gcc,请尝试使用-Wall 选项来获取所有警告。如果您使用 Eclipse 之类的 IDE,它会自动执行此操作。

        【讨论】:

          猜你喜欢
          • 2017-07-04
          • 1970-01-01
          • 2016-08-27
          • 2014-12-25
          • 1970-01-01
          • 1970-01-01
          • 2018-09-24
          • 1970-01-01
          相关资源
          最近更新 更多