gdb“程序正常退出”当它不应该
Posted
技术标签:
【中文标题】gdb“程序正常退出”当它不应该【英文标题】:gdb "Program exited normally" when it shouldn't 【发布时间】:2011-12-09 23:17:03 【问题描述】:我正在使用 gcc44 和 gdb 在 64 位 Linux CentOS 5.7 服务器上调试一些 ANSI C 代码。
在我的一个函数的中间,我有一个循环 192 次的 for 循环(循环中有 2 行代码)。如果我在 for 循环开始时设置 gdb 并设置断点,我可以单步执行 for 循环 192 次,然后它会退出 for 循环并在 for 循环之后继续执行下一行代码。这都是使用“s”或“n”逐步执行 gdb 中的代码。一切正常。
现在,我不再使用“s”或“n”单步执行 for 循环以到达 for 循环之后的下一行代码,而是启动 gdb,然后在该行结束后的行设置断点for 循环。如果我然后在 gdb 中按“c”,它会给我“程序正常退出”。我希望 gdb 在 for 循环之后的代码行上的这个断点处停止。 (!?)
作为另一个实验,我了解到 gdb 确实成功地停止在任何行上设置的任何断点之后紧跟 for 循环之后的代码行。
从诸如此类的问题来看,也许其他人有过这种经历(其中还有 2 个额外的参考资料):
gdb error "Program exited normally"
它在 gdb 中是可重复的。在没有深入研究相关代码的情况下,任何人之前都看到过这种行为和/或知道我可以检查什么?
编辑 1
如果我在断点行包含printf("\n");
会导致上述问题,将该行上的内容移动到此 printf 代码下方的一行,则一切正常(例如 gdb 在 printf 行上停止)。
我什至可以在之前有问题的代码行上成功设置断点,现在是 printf 行之后的下一行。奇怪!
【问题讨论】:
线程问题?使用调试器单步执行将很好地隐藏竞争条件。 W/O 最少的代码或回溯 (bt),任何人都很难为您提供帮助。 如果是竞争条件阻止 gdb 正常运行,那么是否也会阻止程序正常运行(不使用 gdb 时)?如果是这样,我什至不会意识到它正在发生,如果不是因为这次奇怪的事故——人们如何解决这种情况? 一种解决方法是使用 'u'ntil 命令退出循环。 我不熟悉...它是如何工作的?是 gdb 命令吗? 你编译过优化了吗? 【参考方案1】:你的编译器在欺骗你。
嗯,不是真的,但它并没有完全按照你的怀疑做。
编译器的第一个原则概念是将 C 的每一行按顺序转换为一条或多条汇编指令,并按照与 C 代码相同的顺序执行汇编。
实际上,编译器会重新组织事物以优化速度或空间。如果一条指令被认为对程序状态没有净影响,它可以被完全删除。因此,当您告诉 GDB 在那一行中断时,嗯.. 没有带有调试信息的汇编指令指向 C 的那一行。
【讨论】:
感谢 gravitron。参考上面文章中的最后一句话,GDB 可以停在有问题的代码行上,具体取决于它在代码中的位置。如果在 for 循环和这行有问题的代码之间插入了新的(虚拟)代码,那么 GDB 会突然开始看到这个有问题的代码。也许这是乔上面建议的比赛条件?不确定。 我怀疑这是一种竞争条件。更有可能的是,有问题的行在没有 printf 的情况下是不相关的,并且可能与 printf 相关(编译器无法判断)。例如,如果将值传递给 printf,编译器将不再优化冗余调用,因为它不知道 printf 是否修改了它。以上是关于gdb“程序正常退出”当它不应该的主要内容,如果未能解决你的问题,请参考以下文章