C 无法在gdb中复制segfault

C 无法在gdb中复制segfault,c,gdb,C,Gdb,当我运行我的项目时,我会犯错误。每次我在gdb中运行程序时,SEGD故障都会消失。这种行为不是随机的:每次我在shell中运行它时,它都会出现segfaults,每次我在gdb中运行它时,segfaults都会消失。(我确实使用了-g重新编译) 因此,在我开始疯狂地在代码中添加printfs之前,我想知道一些事情: 这种行为普遍吗 解决这个问题的最佳方式是什么 我不知道测试是否可以编写脚本,因为我的应用程序是交互式的,并且在特定的用户输入上崩溃 我没有将代码粘贴到这里,因为它太长了。但如果有

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

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

  • 这种行为普遍吗
  • 解决这个问题的最佳方式是什么
我不知道测试是否可以编写脚本,因为我的应用程序是交互式的,并且在特定的用户输入上崩溃

我没有将代码粘贴到这里,因为它太长了。但如果有人有兴趣帮忙,这里是:
它是否进行核心转储?以便在调试器中加载核心转储。否则,请更改代码以使其执行核心转储。

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

这种行为普遍吗

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

解决这个问题的最佳方式是什么


一盎司预防抵得上一吨治疗;学习未定义行为的常见原因,养成良好习惯,避免写下这些习惯。一旦发现问题,静态分析代码通常是一个好主意;仔细检查并说服自己,证明索引将保持在边界内,数据将适合其数组,无效指针不会被取消引用等。

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

$ ulimit -c unlimited
然后运行你的程序。它将生成一个
core
文件

然后使用gdb:

$ gdb ./program core

gdb将加载,您可以运行回溯以查看究竟是什么操作导致了SEGFULT。

尝试在
valgrind
中运行您的应用程序,如果您的平台上有此功能。当使用
-g
编译时,您的程序是否运行时没有SEGFULT,但不能在gdb中运行?欢迎来到海森堡的奇妙世界。你有?如果是,就用它。您是否至少使用“
gcc-g-Wall-Werror
”进行编译?如果没有,请将代码放到您可以使用的位置。考虑向代码行添加'<代码> -> Wextra >代码>。你有堆芯吗?如果没有,请重新启用它们(
ulimit-c unlimited
),至少让gdb告诉您崩溃发生在哪里。尝试使用
-Wextra-pedantic
以及
-Wall/-Wextra
进行编译,它可能会发现一些问题。如果失败,你可以设置自己获取一个内核转储(如果默认情况下你没有得到它们,那么在ubuntu上使用
ulimit-c
),然后用
gdb myprogram mycore
将其加载到gdb中。或者你可以安装一个segfault处理程序并打印回溯(希望bug不会弄乱堆栈)。