所以我正在调试这个程序,这个程序是我从即将毕业的博士生中继承的,或者是在学生完成论文后发生的任何事情。无论如何,现在我有责任进行调试。该程序基本上接受几个文本文件并处理它们。我遇到的问题(段错误)是因为程序试图访问尚未初始化的数组。我想知道是否有任何调试工具可以让你运行程序,并比较程序关闭的两个不同路径。我想我可以手动完成程序,但我宁愿不这样做,因为它相当大,我仍然没有掌握它。我一直在使用GDB和Valgrind(以及使用g ++ -wall来显示警告),这就是我如何做到这一点。但是,是否有任何软件让你按照我上面所描述的那样做,甚至只是让你完成你的程序。
答案 0 :(得分:4)
我认为您正在寻找正确的方向,选择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最接近,因为它还允许您“可视化”所采用的代码路径。
答案 1 :(得分:4)
这些建议特定于GCC。您可以使用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:}
如果您想要实现自己的工具来记录程序的通话记录,可以在GCC上使用-finstrument-functions
及其相关选项。
-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
对该指针进行后期处理。
答案 2 :(得分:3)
GDB可以让您逐行“逐步”完成您的程序。一些提示:
b main
)处中断,然后按n
+ Enter键执行当前行并继续执行下一行。 s
+ Enter键(即进入被调用的功能并从那里继续)。 p
+变量名称以打印出值(真的很好判断该变量是否已初始化,提示提示......)emacs program.c
,然后输入Alt + x
,然后输入gdb
即可。输入可执行文件的名称,然后按Enter键。现在您可以看到更多代码,并仍然使用gdb命令进行调试。