【问题标题】:Cannot reproduce segfault in gdb无法在 gdb 中重现段错误
【发布时间】:2011-08-15 00:00:16
【问题描述】:

我在运行项目时遇到了段错误。每次我在 gdb 中运行程序时,段错误都会消失。这种行为不是随机的:每次我在我的 shell 中运行它时,它都会出现段错误,每次我在 gdb 中运行它时,段错误都会消失。 (我确实使用 -g 重新编译)。

所以在我开始疯狂地在代码中到处添加 printfs 之前,我想知道一些事情:

  • 这种行为常见吗?
  • 解决问题的最佳方法是什么?

我不知道是否可以编写测试脚本,因为我的应用程序是交互式的,并且在特定用户输入时崩溃。

我没有在这里粘贴我的代码,因为它太长了。但如果有人有兴趣帮忙,这里是: https://github.com/rahmu/Agros

【问题讨论】:

  • 尝试在valgrind 中运行您的应用(如果您的平台上可用)。
  • 在使用-g 编译但不在 GDB 中运行时,您的程序是否在没有段错误的情况下运行?
  • 欢迎来到海森堡的奇妙世界。你有valgrind吗?如果是这样,请使用它。您是否至少使用“gcc -g -Wall -Werror”进行编译?如果没有,请让您的代码达到您可以做到的程度。考虑将“-Wextra”添加到该命令行。你有核心转储吗?如果没有,请重新启用它们 (ulimit -c unlimited) 并至少让 gdb 告诉您崩溃发生的位置。
  • 尝试使用-Wextra -pedantic-Wall/-Wextra 进行编译,它可能会有所收获。如果您无法设置自己以获取核心转储(如果默认情况下没有获得它们,请使用 ulimit -c <size> - 无论如何在 ubuntu 上)并使用 gdb myprogram mycore 将其加载到 gdb 中。

标签: c gdb


【解决方案1】:

最简单的解决方法是捕获核心转储:

$ ulimit -c unlimited

然后运行你的程序。它将生成一个core 文件

然后使用gdb:

$ gdb ./program core

gdb 将加载,您可以运行回溯以查看究竟是什么操作引发了段错误。

【讨论】:

    【解决方案2】:

    它是否进行核心转储?这样就可以在调试器中加载核心转储。否则更改代码以使其执行核心转储。

    【讨论】:

    • 或者,您可以安装一个段错误处理程序并打印回溯(并希望该错误不会弄乱堆栈)。
    【解决方案3】:

    我的猜测是,这是一个并发问题,导致引用在方法调用下被释放,假设它拥有的指针将保持有效。 gdb 可能掩盖这一点的原因是因为 GDB 只允许 2 个线程实际同时运行。如果您有超过 2 个线程在运行,那么只有 2 个线程将同时主动运行。 GDB 也有可能掩盖这种特定情况的性能影响。正如 Ed 所说,只需让您的应用程序核心转储,您就可以在 GDB 中打开核心并检查堆栈。

    【讨论】:

      【解决方案4】:

      这种行为常见吗?

      是的。未定义的行为是大多数这些问题的根源,根据定义,它是未定义的。使用-g 重新编译肯定会影响结果。如果编译器使用一些伪随机遗传算法来优化东西或类似的东西,重新编译可能会改变结果。

      解决问题的最佳方法是什么?

      一盎司的预防胜于一吨的治疗;了解未定义行为的常见原因并养成良好习惯以避免编写它们。一旦发现有问题,对代码进行静态分析通常是个好主意;对自己进行推理并证明索引将保持在界限内,数据将适合其数组,无效指针不会被取消引用等。

      【讨论】:

        猜你喜欢
        • 2012-10-24
        • 1970-01-01
        • 2011-04-20
        • 2017-12-21
        • 1970-01-01
        • 1970-01-01
        • 2017-07-04
        • 1970-01-01
        • 2017-09-04
        相关资源
        最近更新 更多