G++是Unix/Linux下C++的编译器,gdb则是Unix/Linux下有力的调试工具。大多数时候,我们编写的C/C++代码并不是运行在Windows上,而是在Linux系统上跑。这里我记录了一些有关于g++和gdb的一些使用方法以备不时之需。

g++的使用

g++在执行编译工作的时候,总共需要4步:

  • 预处理,生成.i的文件,主要是头文件和宏定义的展开:g++ -E test.cpp -o test.i
  • 编译,将预处理后的文件转换成汇编语言,生成文件.s: g++ -S test.i -o test.s
  • 汇编,有汇编变为目标代码(机器代码)生成.o的文件,主要是将.s文件转为二进制文件: g++ -c test.s -o test.o
  • 链接,连接目标代码,生成可执行程序: g++ test.o -o test

以上步骤也可以用一条命令解决:

g++ test.cpp -o test

当涉及多个文件的编译时,有以下两种做法:

$ g++ a.cpp b.cpp c.cpp -o test  #一次性编译所有文件

$ g++ a.cpp -o a.o  #分开编译
$ g++ b.cpp -o b.o
$ g++ c.cpp -o c.o
$ g++ a.o b.o c.o -o test

这里建议采用分开编译的方法,这样当你对其中一个或多个文件进行修改时,只需要对应的编译那一个或多个文件,而不需要从头开始编译。


常用的g++选项:

命令描述
-Wall编译时输出一些警告和错误信息
-c只编译不连接
-E对源文件进行预处理
-S将预处理后的文件转为汇编文件
-o指定输出文件名
-I指定一个包含头文件的路径
-l指定一个附加库
-L指定一个附加的库路径
-shared生成动态库文件

Linux下文件的类型是不依赖于其后缀名的,但一般来讲: .o是目标文件,相当于windows中的.obj文件 .so为共享库,是shared object,用于动态连接的,和.dll差不多 .a为静态库,是好多个.o合在一起,用于静态连接 .la为libtool自动生成的一些共享库,主要记录了一些配置信息。

gdb的使用

.cpp在编译时要加上-g选项,生成的可执行文件才能用gdb进行源码级调试

g++ -g test.cpp -o test

值得注意的是,-g分4个等级:

  • g0等于不加-g。即不包含任何信息
  • g1只包含最小信息,一般来说只有你不需要debug,只需要backtrace信息,并且真的很在意程序大小,或者有其他保密/特殊需求时才会使用-g1。
  • g2为gdb默认等级,包含绝大多数你需要的信息。
  • g3包含一些额外信息,例如包含宏定义信息。当你需要调试宏定义时,请使用-g3

一般来说,gdb主要帮助你完成下面四个方面的功能:

  1. 启动程序,可以按照自定义的要求运行程序。

  2. 可以让调试程序在指定的位置的断点处停止。

  3. 当程序停止时,可以检查此时程序中所发生的事情。

  4. 动态的改变程序的执行环境。

几种方法在gdb下运行程序:

  • gdb ${程序} 进入gdb后,输入run(简写r) ${arg1} ${arg2} … ${argN}
  • gdb --args ${程序} ${arg1} ${arg2} … ${argN}进入gdb后,运行run
  • 进入gdb后,输入file ${程序}。然后使用set args ${arg1} ${arg2} … ${argN}设定好程序参数,再运行run

常用gdb调试命令:

命令描述
start开始执行程序,停在主函数第一行语句前面
backtrace/bt查看各级函数调用,显示栈信息
step/s单步调试,步入当前函数
next/n单步调试,步过当前函数
until/u执行到当前循环完成
continue/c继续运行程序
finish执行到当前函数返回
list/l列出源代码,一次10行
list <行号>列出从第几行开始的源代码
list <函数名>列出函数源代码
print/p <表达式>打印表达式的值
frame/f x切换到第x帧,其中x会在bt命令中显示,从0开始,0表示栈顶
up/down x往栈顶/栈底移动x帧,当不输入x时,默认为1
info/i locals打印当前栈帧的本地变量
set var x修改当前x变量的值
break <行号>源文件指定行号设置断点
break <函数名>源文件指定函数设置断点
break <行号/函数名> if <条件>设置条件断点,满足条件时则在设置处断开
watch <变量>写监视指定变量,当变量发生变化时停止程序运行
rwatch <变量>读监视指定变量,当变量被读取时停止程序运行
awatch <变量>读写监视指定变量,当变量发生变化或被读取时程序停止运行
delete <行号/函数名>删除断点
info/i b查看断点信息
save breakpoint <文件名>.dp断点保存在指定文件中
-x <文件名>.dp该选项读取指定文件,恢复文件中的断点设置
quit退出gdb调试

参考

macky0668——linux下c++的编译器g++的基本使用

爱折腾的西山居士——GDB常用命令系列

改变自己chenyu——linux之gdb基本调试命令和使用总结

gdb 调试入门,大牛写的高质量指南