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
当涉及多个文件的编译时,有以下两种做法:
1 | g++ a.cpp b.cpp c.cpp -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主要帮助你完成下面四个方面的功能:
启动程序,可以按照自定义的要求运行程序。
可以让调试程序在指定的位置的断点处停止。
当程序停止时,可以检查此时程序中所发生的事情。
动态的改变程序的执行环境。
几种方法在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调试 |