我正在调试这个程序,它是从即将毕业的博士生那里继承来的。该程序接受几个文本文件并对其进行处理。我遇到的问题是一个段错误,因为程序尝试访问尚未初始化的数组。我想知道是否有任何调试工具可以让您运行程序并比较程序运行过程中两条不同的路径。虽然我可以手动检查程序,但我不愿意这样做,因为它相当大,并且我还没有完全掌握它。我一直在使用GDB和Valgrind(以及使用g++ - wall显示警告),这就是我取得进展的方式。但是否有任何软件可以让您执行上述操作,甚至只是逐步执行程序。
我正在调试这个程序,它是从即将毕业的博士生那里继承来的。该程序接受几个文本文件并对其进行处理。我遇到的问题是一个段错误,因为程序尝试访问尚未初始化的数组。我想知道是否有任何调试工具可以让您运行程序并比较程序运行过程中两条不同的路径。虽然我可以手动检查程序,但我不愿意这样做,因为它相当大,并且我还没有完全掌握它。我一直在使用GDB和Valgrind(以及使用g++ - wall显示警告),这就是我取得进展的方式。但是否有任何软件可以让您执行上述操作,甚至只是逐步执行程序。
gcov
覆盖工具,获取程序已执行部分及频率的详细记录。您需要向GCC传递一些特殊选项,以生成适当的仪器和输出,供gcov
处理。
然后,在执行程序时,会生成一些分析和覆盖数据。然后,您可以调用
--coverage
此选项用于编译和链接为覆盖分析而仪器化的代码。该选项是-fprofile-arcs -ftest-coverage
(编译时)和-lgcov
(链接时)的同义词。有关这些选项的更多详细信息,请参阅文档。
gcov
来分析该输出。下面是从上面链接中获取的输出示例: -: 0:Source:tmp.c
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <stdio.h>
-: 2:
-: 3:int main (void)
1: 4:{
1: 5: int i, total;
-: 6:
1: 7: total = 0;
-: 8:
11: 9: for (i = 0; i < 10; i++)
10: 10: total += i;
-: 11:
1: 12: if (total != 45)
#####: 13: printf ("Failure\n");
-: 14: else
1: 15: printf ("Success\n");
1: 16: return 0;
-: 17:}
-finstrument-functions
及其相关选项。生成入口和出口函数的插桩调用,在函数进入后和退出前,使用当前函数的地址和其调用站点调用以下分析函数。(在某些平台上,__builtin_return_address
无法超出当前函数工作,因此调用站点信息可能无法对分析函数可用。) void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
第一个参数是当前函数起始地址,可以在符号表中精确查找。
在C++中,这些钩子的实现应该声明为extern "C"
。你可以实现这些钩子来记录每次调用函数时的信息。你无法得到函数名称,但可以使用objdump
或addr2line
后处理指针。
我认为你选择像GDB和valgrind这样的工具是正确的方向。
GDB可以脚本执行程序并查看调用栈,在segfault发生时可以在该位置设置断点并使用不崩溃的参数再次运行程序,然后比较两者的差异。
使用valgrind,它实际上是一套工具(http://valgrind.org/info/tools.html),您可以使用callgrind和kcachegrind取得一些成功。Callgrind为您提供调用图,而kcachegrind (http://kcachegrind.sourceforge.net/cgi-bin/show.cgi/KcacheGrindIndex) 允许您对其进行可视化。我在对大型C代码库进行性能分析时都使用了它们。
另一个可以帮助您的工具是Fenris (http://lcamtuf.coredump.cx/fenris/whatis.shtml),它还可以打印出您代码的调用图。阅读您的要求时,我认为Fenris最接近,因为它还允许您“可视化”所采取的代码路径。
GDB可以让您逐行“步进”执行程序。以下是一些提示:
b main
),按下n
+ Enter键以执行当前行并继续到下一行。s
+ Enter键。p
+ 变量名以打印出该值(非常好,可以告诉您该变量是否已初始化,提示……)emacs program.c
,然后键入Alt + x
,再键入gdb
。输入可执行文件的名称,然后按Enter键。现在您可以看到更多代码,并仍然使用gdb命令进行调试。