如何通过优化标志跟踪代码行为的原因

时间:2015-12-18 17:07:17

标签: c gcc optimization valgrind

所以我有一些复杂的C代码,它通过纠错对位数组进行编码和解码。该代码基于this,并根据我的需要进行了修补(因此它的功能与链接代码的功能相同,但核心除外)。

关闭优化后,我得到了我对输出的期望。通过完全优化(即在gcc编译期间提供-O3),代码的行为方式不同。

我试图弄清楚我应该寻找什么来追踪这一点;因为在我开始在代码中的任何地方添加printf以查看优化之间输出不同的行之前,我可以找到一些显而易见的优化。

我认为,一个线索是,当我通过valgrind运行代码时,没有优化,我没有得到任何错误或警告:

==5112== Memcheck, a memory error detector
==5112== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5112== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==5112== Command: ./a.out
==5112== 
!!!!! decode ret = 0 (my output)
Nid decoded = 0010100100111010101110101001001110111110110000100110101000101011 (my output)
==5112== 
==5112== HEAP SUMMARY:
==5112==     in use at exit: 0 bytes in 0 blocks
==5112==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==5112== 
==5112== All heap blocks were freed -- no leaks are possible
==5112== 
==5112== For counts of detected and suppressed errors, rerun with: -v
==5112== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

启用优化并且--track-origins = yes,valgrind报告以下内容:

==5506== Memcheck, a memory error detector
==5506== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5506== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==5506== Command: ./a.out
==5506== 
==5506== Conditional jump or move depends on uninitialised value(s)
==5506==    at 0x400DC1: bch_decode (in /home/directory/bch/a.out)
==5506==    by 0x4005CD: main (in /home/directory/bch/a.out)
==5506==  Uninitialised value was created by a stack allocation
==5506==    at 0x40094B: bch_decode (in /home/directory/bch/a.out)
==5506== 
==5506== Use of uninitialised value of size 8
==5506==    at 0x400DC3: bch_decode (in /home/directory/bch/a.out)
==5506==    by 0x4005CD: main (in /home/directory/bch/a.out)
==5506==  Uninitialised value was created by a stack allocation
==5506==    at 0x40094B: bch_decode (in /home/directory/bch/a.out)
==5506== 
!!!!! decode ret = -1
Nid decoded = 0010100100111010101110101001001110111110110000100010101000101011
==5506== 
==5506== HEAP SUMMARY:
==5506==     in use at exit: 0 bytes in 0 blocks
==5506==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==5506== 
==5506== All heap blocks were freed -- no leaks are possible
==5506== 
==5506== For counts of detected and suppressed errors, rerun with: -v
==5506== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

然而,通过优化,我不认为Valgrind可以告诉我具体的行号或发生这种情况的变量。即使我使用GDB逐步完成代码,由于优化,也很难确定这一点。

有没有办法可以对此进行排序,可能/模拟/优化行为,但在调试信息中保留正确的行号和变量名称(不太可能是我目前所读的所有内容)。< / p>

任何有助于推动这一进展的人都会非常感激。

2 个答案:

答案 0 :(得分:1)

valgrind告诉你,你有未初始化的变量:

==5506== Conditional jump or move depends on uninitialised value(s)
==5506==    at 0x400DC1: bch_decode (in /home/directory/bch/a.out)
==5506==    by 0x4005CD: main (in /home/directory/bch/a.out)
==5506==  Uninitialised value was created by a stack allocation
==5506==    at 0x40094B: bch_decode (in /home/directory/bch/a.out)
==5506== 
==5506== Use of uninitialised value of size 8
==5506==    at 0x400DC3: bch_decode (in /home/directory/bch/a.out)
==5506==    by 0x4005CD: main (in /home/directory/bch/a.out)
==5506==  Uninitialised value was created by a stack allocation
==5506==    at 0x40094B: bch_decode (in /home/directory/bch/a.out)

使用-g标志重新编译并重新链接您的代码,以查看valgrind输出中的行号。

答案 1 :(得分:0)

步骤1 - 使用任何可用的静态分析工具,从您选择的编译器上提供的最大警告级别开始。有时使用不同的编译器(例如llvm)可能会产生新的警告,而第一个没有给你。

Valgrind说你有未初始化的变量问题,所以&#34; gcc -Wall&#34;可能会钉它。

第2步 - 在代码构建-g上尝试valgrind;也许你会得到行号。 (或者它可能会因为-g与-O的交互而停止复制。)

步骤3a - 强烈的代码审查,寻找未定义的行为。你如何理解&#34;序列点&#34;在C?

如果有任何多线程,信号处理等,则查找订购问题。 (与代码的声明目的不同,但是与优化器相关的破坏的常见来源。)

步骤3b - 检查在两个实例中生成的汇编代码。考虑使用调试器在汇编级而不是源代码级执行代码。

步骤3c - 启用/禁用单个优化,并查看哪个优化。然后使用了解优化的作用来指导代码审查

步骤3d - 简化您的代码。这项工作可能会导致疏忽。如果没有,你可以开始调用它的各个部分,并检查哪些位行为不当。 (一旦你看到正确的线条,你就会发现错误。)