什么是调试优化的C / C ++程序的有效方法?

时间:2009-09-07 02:37:38

标签: c++ c debugging disassembly

我多次使用优化代码(有时甚至涉及矢量化循环),其中包含错误等。如何调试这样的代码?我正在寻找任何类型的工具或技术。我使用以下(可能是过时的)工具,所以我希望升级。

我使用以下内容:

  • 由于使用ddd,你看不到代码,我使用gdb + dissambler命令查看生成的代码;我无法使用此功能逐步完成该程序。
  • ndisasm

由于

4 个答案:

答案 0 :(得分:19)

调试优化程序总是比较困难,但总有办法。一些额外的提示:

  • 进行调试构建,看看你是否在调试版本中遇到了同样的错误。如果您不需要,则无需调试优化版本。
  • 如果在支持它的平台上使用valgrind。您看到的错误可能更难理解,但提前发现问题通常会简化调试。
  • printf调试是原始的,但如果您遇到只出现在优化版本中的复杂问题,有时这是最简单的方法。
  • 如果您怀疑计时问题(特别是在多线程程序中),请滚动您自己的断言版本,如果违反条件则中止或打印,并在几个选定的位置使用它,以排除可能的问题。
  • 看看你是否可以在不使用-fomit-frame-pointers的情况下重现问题,因为这会使代码很难调试,并且启用-O2或-O3。这可能会为您提供足够的信息来查找问题的原因。
  • 隔离代码的一部分,构建测试套件,看看是否可以识别出任何失败的测试用例。调试一个函数要比整个程序容易得多。
  • 尝试使用-fno-X选项逐个关闭优化。这可能会帮助您找到严格的别名问题等常见问题。
  • 启用更多编译器警告。有些事情,比如严格的别名问题,如果它们在不同的优化级别之间产生行为差异,就会产生编译器警告。

答案 1 :(得分:7)

调试发布版本时,可以放入__asm nops;作为断点的占位符(int 3)。这很好,因为您可以保证断点位置而不会弄乱编译器优化或编写printf / cout语句。

答案 2 :(得分:1)

当然,调试非优化版本总是更容易。如果做不到这一点,反汇编代码会很有帮助。我使用过的其他技术包括通过强制打印或记录中间结果,或者将关键变量更改为“volatile”来部分去优化代码,这样我至少可以查看中的值。调试器。

答案 3 :(得分:0)

你可以称之为优化代码的优化代码是为了削减循环(这会使调试变得困难),但实际上并没有真正优化。 Here is an example of what I mean.

我会关闭编译器优化,自己调试和调整,然后如果代码中有热点实际上是编译器看到的代码(不在外部库中),则重新启用编译器优化。 (我将热点定义为经常找到PC的代码的一部分。这会自动豁免包含函数调用的循环,因为它们会偷走PC。)