[英]Is there a way to compare two different runs of a C/C++ program?
So I'm working on debugging this program that I inherited from this PhD student who's about to graduate, or whatever happens after a student finishes their thesis. 所以我正在调试这个程序,这个程序是我从即将毕业的博士生中继承的,或者是在学生完成论文后发生的任何事情。 Anyway, it's now my responsibility to debug it.
无论如何,现在我有责任进行调试。 The program basically takes in a couple of text files and processes them.
该程序基本上接受几个文本文件并处理它们。 The problem I've been experiencing (a segfault) occurs because the program tries to access an array that has not been initisialized yet.
我遇到的问题(段错误)是因为程序试图访问尚未初始化的数组。 I was wondering if there's any debugging tool that lets your run through the program, and compare the two different paths the program goes down.
我想知道是否有任何调试工具可以让你运行程序,并比较程序关闭的两个不同路径。 I suppose I could go through the program manually, but I would rather not do that as it is rather large, and I still haven't mastered it.
我想我可以手动完成程序,但我宁愿不这样做,因为它相当大,我仍然没有掌握它。 I've been using GDB and Valgrind (as well as using g++ -wall to show warnings), which is how I've gotten this far.
我一直在使用GDB和Valgrind(以及使用g ++ -wall来显示警告),这就是我如何做到这一点。 But is there any software that let's you do what I've described above, or even just steps you through your program.
但是,是否有任何软件让你按照我上面所描述的那样做,甚至只是让你完成你的程序。
I think you are looking in the right direction with your choice of tools like GDB and valgrind. 我认为您正在寻找正确的方向,您可以选择GDB和valgrind等工具。
With GDB, you can script the execution of the program under both conditions and look at the call stack when the segfault occurs. 使用GDB,您可以在两种条件下编写程序的执行脚本,并在发生段错误时查看调用堆栈。 You can then put a breakpoint at that location and run again with the parameters that do not crash the program and investigate the difference in both.
然后,您可以在该位置放置一个断点,并使用不会使程序崩溃的参数再次运行,并调查两者的差异。
Using valgrind, which is actually a suite of tools ( http://valgrind.org/info/tools.html ), you can have some success using callgrind and kcachegrind. 使用valgrind,它实际上是一套工具( http://valgrind.org/info/tools.html ),使用callgrind和kcachegrind可以取得一些成功。 Callgrind gives you call graphs and kcachegrind ( http://kcachegrind.sourceforge.net/cgi-bin/show.cgi/KcacheGrindIndex ) allows you to visualize them.
Callgrind为您提供调用图,kcachegrind( http://kcachegrind.sourceforge.net/cgi-bin/show.cgi/KcacheGrindIndex )允许您对它们进行可视化。 I used them both for performance profiling of large C code bases.
我将它们用于大型C代码库的性能分析。
Another tool that can help you is Fenris ( http://lcamtuf.coredump.cx/fenris/whatis.shtml ), which also can print out a call graph of your code. 另一个可以帮助你的工具是Fenris( http://lcamtuf.coredump.cx/fenris/whatis.shtml ),它也可以打印出代码的调用图。 When reading your requirements, I think Fenris comes closest as it also allows you to 'visualise' the code path taken.
在阅读您的要求时,我认为Fenris最接近,因为它还允许您“可视化”所采用的代码路径。
These suggestions are specific to GCC. 这些建议特定于GCC。 You can use the
gcov
coverage tool to get a detailed account of which parts of a program have been executed and how often. 您可以使用
gcov
coverage工具详细说明程序的哪些部分已执行以及执行频率。 You have to pass some special options to GCC to generate the proper instrumentation and output for gcov
to process. 您必须将一些特殊选项传递给GCC,以便为
gcov
生成适当的检测和输出。
--coverage
This option is used to compile and link code instrumented for coverage analysis.--coverage
此选项用于编译和链接用于覆盖率分析的代码。 The option is a synonym for-fprofile-arcs -ftest-coverage
(when compiling) and-lgcov
(when linking).该选项是
-fprofile-arcs -ftest-coverage
(编译时)和-lgcov
(链接时)的-lgcov
。 See the documentation for those options for more details.有关更多详细信息,请参阅这些选项的文档。
Then, when you execute your program, some profiling and coverage data is generated. 然后,当您执行程序时,会生成一些分析和覆盖数据。 You can then invoke
gcov
to analyze that output. 然后,您可以调用
gcov
来分析该输出。 Below is a example of output taken from the link above: 以下是从上面的链接获取的输出示例:
-: 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:}
If you want to implement your own instrumentation to log the call history of the program, you can use the -finstrument-functions
and its related options on GCC. 如果要实现自己的检测以记录程序的调用历史记录,可以在GCC上使用
-finstrument-functions
及其相关选项。
-finstrument-functions
Generate instrumentation calls for entry and exit to functions.生成用于进入和退出函数的检测调用。 Just after function entry and just before function exit, the following profiling functions are called with the address of the current function and its call site.
在函数输入之后和函数退出之前,使用当前函数的地址及其调用站点调用以下分析函数。 (On some platforms,
__builtin_return_address
does not work beyond the current function, so the call site information may not be available to the profiling functions otherwise.)(在某些平台上,
__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);
The first argument is the address of the start of the current function, which may be looked up exactly in the symbol table.
第一个参数是当前函数的开始地址,可以在符号表中准确查找。
In C++, your implementation of those hooks should be declared as extern "C"
. 在C ++中,您对这些钩子的实现应该声明为
extern "C"
。 You can implement the hooks to log each time a function is called. 每次调用函数时都可以实现钩子记录。 You don't get the function names, but you can post process the pointers afterward with
objdump
or addr2line
. 您没有获取函数名称,但您可以使用
objdump
或addr2line
在后面处理指针。
GDB can allow you to 'step' through your program line by line. GDB可以让您逐行“逐步”完成您的程序。 Some tips:
一些技巧:
b main
), and press n
+ Enter key to execute current line and move on to the next one. b main
),然后按n
+ Enter键执行当前行并继续执行下一行。 s
+ Enter key if you want to step into the function (ie go into the function that is called and go on from there). s
+ Enter键(即进入被调用的功能并从那里继续)。 p
+ variable name to print out the value (really good to tell if that variable is initialized or not, hint hint...) p
+变量名来打印出来的值(非常好判断该变量是否已初始化,提示提示......) emacs program.c
, and type Alt + x
, then type gdb
. emacs program.c
,然后键入Alt + x
,然后键入gdb
。 Type in the name of your executable, and press Enter.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.