hig*_*241 6 c c++ debugging gdb valgrind
所以我正在调试这个程序,这个程序是我从即将毕业的博士生中继承的,或者是在学生完成论文后发生的任何事情.无论如何,现在我有责任进行调试.该程序基本上接受几个文本文件并处理它们.我遇到的问题(段错误)是因为程序试图访问尚未初始化的数组.我想知道是否有任何调试工具可以让你运行程序,并比较程序关闭的两个不同路径.我想我可以手动完成程序,但我宁愿不这样做,因为它相当大,我仍然没有掌握它.我一直在使用GDB和Valgrind(以及使用g ++ -wall来显示警告),这就是我如何做到这一点.
这些建议是针对 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:}
Run Code Online (Sandbox Code Playgroud)
如果要实现自己的检测来记录程序的调用历史记录,可以使用-finstrument-functionsGCC 上的 及其相关选项。
-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);
Run Code Online (Sandbox Code Playgroud)
第一个参数是当前函数的起始地址,可以在符号表中准确查找。
在 C++ 中,这些钩子的实现应该声明为extern "C". 您可以实现钩子以在每次调用函数时记录日志。您不会获得函数名称,但您可以在之后使用objdump或对指针进行后期处理addr2line。
我认为您选择 GDB 和 valgrind 等工具的方向是正确的。
使用 GDB,您可以在两种情况下编写程序执行脚本,并在发生段错误时查看调用堆栈。然后,您可以在该位置放置一个断点,并使用不会使程序崩溃的参数再次运行,并调查两者之间的差异。
使用 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 最接近,因为它还允许您“可视化”所采用的代码路径。
| 归档时间: |
|
| 查看次数: |
1384 次 |
| 最近记录: |