gprof
gprof 是 GNU Profiler 的简称,是一个用于性能分析的工具,主要用于分析 C、C++ 以及其他支持的编程语言编写的程序。它的主要功能是帮助开发者找出程序的性能瓶颈,从而优化代码。gprof 的工作原理是通过插入代码段来记录程序的运行时间和调用关系,然后生成性能分析报告。
在Makefile中添加-pg
使用gprof之前,要先在Makefile的编译器中添加-pg,可以在icc后面添加,也可以在CCFLAGS后面添加
使用gprof分析
(1)在终端直接输入gprof ./main,可以在终端直接看到gprof的分析结果
(2)在执行gprof ./main命令之后,项目文件会生成gmon.out文件,可以将gmon.out中的分析结果存储在txt文件中。因此可以在终端直接输入命令gprof ./main gmon.out > analysis.txt。执行完命令之后,项目文件中会出现analysis.txt文件,文件中包含gprof的分析结果。之后可以输入命令cat analysis.txt直接查看结果。
gprof的分析结果
valgrind
Valgrind 是一个用于内存调试、内存泄漏检测和性能分析的工具框架。它主要用于 C 和 C++ 程序,但也支持其他使用类似内存管理模型的编程语言。Valgrind 提供了一组工具,可以帮助开发者检测程序中的内存错误、内存泄漏、并发错误等问题,从而提高程序的稳定性和性能。
memcheck
这是 Valgrind 最常用的工具,用于检测内存错误,如非法读取和写入、使用未初始化的内存、内存泄漏等
首先要在makefile中添加关于memcheck的命令
之后直接输入make memcheck命令,执行命令,终端便会显示内存的检测结果
callgrind和Cachegrind
Callgrind:用于分析程序的调用图和性能瓶颈,Cachegrind:用于分析程序的缓存使用情况和性能。
输入命令valgrind --tool=callgrind ./main
执行命令后,项目中会生成callgrind.out.xxx文件
用kcachegrind可以可视化函数调用结果,输入命令kcachegrind callgrind.out.xxx
kcachegrind可视化结果
输入命令callgrind_annotate callgrind.out.xxx,可以查看文件分析结果
gdb
GDB(GNU Debugger)是 GNU 项目的一部分,是一个功能强大的调试器,主要用于调试 C、C++ 和其他支持的编程语言编写的程序。GDB 允许程序员在程序运行时进行调试,包括设置断点、单步执行代码、检查变量和内存等。
编译程序
为了使用 GDB 进行调试,需要在编译时添加调试信息。使用 -g 选项编译程序:
gcc -g -o my_program my_program.c
启动gdb
在命令行中启动 GDB,并指定要调试的程序:
gdb ./my_program
运行程序
在 GDB 提示符下,使用 run 命令启动程序:
(gdb) run
设置断点
使用 break 命令在特定行或函数上设置断点。例如,在 main 函数的第一行设置断点:
(gdb) break main
在第10行设置断点
(gdb)break 10
单步执行
使用 next 命令逐行执行代码,或者使用 step 命令进入函数内部执行
(gdb) next
(gdb) step
检查变量
使用 print 命令查看变量的值。例如,查看变量 x 的值:
(gdb) print x
查看调用栈
使用 backtrace 命令查看调用栈
(gdb) backtrace
继续执行
使用 continue 命令让程序继续运行,直到下一个断点或程序结束:
(gdb) continue
退出 GDB
使用 quit 命令退出 GDB:
(gdb) quit
gdb <optimized out>
问题
根据您提供的信息"this=0x7fffffffdc50, __in_chrg=",这是在使用GDB调试时遇到的一种情况,其中<optimized out>
表示GDB无法获取变量的值,因为该变量在编译时被优化掉了。这通常发生在代码被使用了高级别的优化选项(如O2、O3)编译时。
针对这种情况,有几种解决方法可以尝试:
- 降低优化级别:将GCC的优化选项调整为O1或O0。在O2、O3优化选项下,编译器会进行更多的优化,可能会导致GDB无法获取变量的信息。将优化级别降低到O0可以完全关闭优化,保留所有变量和代码信息。使用O1优化选项也有可能让您能够查看变量的值。
- 输出打印信息:直接在代码中添加打印语句,将变量的信息打印到屏幕上。这样可以绕过GDB无法获取变量值的问题,直接查看变量的值。
- 使用断点:在代码中设置断点,当程序执行到断点处时,可以通过GDB查看变量的值。这种方法可以绕过一些优化导致的问题,但需要注意断点的设置位置和数量,以免影响程序执行。