gcc 和 gdb 常用选项

gcc

编译步骤

  1. 预处理,生成 .i 的文档[预处理器 cpp]:cpp test.c -o test.i
  2. 编译,得到汇编代码 .s [编译器 cc1]:/usr/local/gcc-4.8.1/libexec/gcc/x86_64-unknown-linux-gnu/4.8.1/cc1 test.i
  3. 汇编,得到目标代码(机器指令).o [汇编器 as]:as test.s -o test.o
  4. 链接目标代码,生成可执行程序[链接器 ld]:ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o test test.o /usr/lib64/crt1.o /usr/lib64/crti.o

对应的编译选项:

  • -o filename:指定输出文件名,默认是 a.out。默认编译的四个阶段会一次执行完,除非指定了停留在某一步。
  • -E:只进行预处理
  • -S:只编译,不汇编,得到汇编代码
  • -c:只编译汇编,不链接,得到可重定位的目标文件

文件后缀

gcc 通过文件名后缀来识别文件,常用后缀有:

  • .c :C 语言源代码
  • .i :预处理过的 C 语言源代码
  • .s :汇编源代码
  • .o :编译后的目标代码
  • .h :C 语言头文件
  • .a :由目标文件构成的档案库文件

gcc 常用选项

参考:
https://www.cnblogs.com/tianyajuanke/p/3359100.html

头文件和库文件处理

  • -I dir:在头文件的搜索路径列表中,添加 dir 目录。当前目录和缺省目录(/usr/include && /usr/local/include)不用指定。
  • -L dir:在库文件的搜索路径列表中,添加 dir 目录。Linux 默认在 /usr/lib 目录中查找

调试 debug 选项和优化选项
在 gcc 编译源代码时指定 -g 选项可以产生带有调试信息的目标代码,gcc 可以为多个不同平台的不同调试器提供调试信息。gcc 默认产生的调试信息是为 gdb 使用的,可以使用 -gformat 指定生成其他平台的其他调试器的调试信息。

-g            //在编译时生成原生格式的调试符号信息,可以使用 gdb 或 ddx 等调试器调试。-g 分为三个级别,默认为 -g2,其中 -g3 除包含 -g2 中的所有调试信息外,还包含源代码中定义的宏。
-ggdb          //在编译时生成 gdb 专用格式(DWARF 2,stabs等)的调试符号信息,信息更为丰富,但只能使用 gdb 调试,而不能使用其它调试器。级别设定与 -g 基本相同。
-gdwarf        //如果升级 GCC 之后,发现 GDB 不能用了,那么在编译的时候加上 -gdwarf 选项试一下,如果还不行,再使用 -gdwarf-2 试试。
-p           //将剖析(Profiling)信息加入到最终生成的二进制代码中,生成可以被通用剖析工具(Prof)能够识别的统计信息,它对于找出程序瓶颈很有帮助。生成后的可执行文件要运行一次,才能生成剖析文件,默认文件名是 gmon.out。
-pg            //生成只有 GNU 剖析工具(Gprof)才能识别的统计信息。
-save-temps     //保存编译过程中生成的一系列中间文件。
-On          //n 可以为 0~3,默认为 1,数字越大优化越高,一般使用 -O2 可以在优化长度、编译时间和代码大小之间取得较好平衡,开发调试建议使用 -O0 没有优化。优化不可与 `-g` 同时使用
-Os          //相当于 -O2.5,使用了所有 -O2 的优化选项,但却没有使用增加大小。也就是说,相对于 -O2,能减少一点可执行文件的大小。
-s          //从执行文件中删除符号表与重定向信息,以减少执行文件的大小。跟直接编译之后,使用 strip 命令减小文件大小效果一致。

静态检查

-pedantic     //检查代码是否符合 ANSI/ISO 标准:
-Wall       //输出警告信息
-Wextra      //输出更多的警告信息
-Weffc++      //检查是否符合 《Effective C++》这本书中提到的标准
-w        //关闭所有警告
  • -static:此选项将禁止使用动态库,只链接静态库,编译后的可执行文件体积大,但可以独立运行,不需要动态链接库

  • -share:此选项将尽量使用动态库,所以生成文档比较小,但是需要系统由动态库.

  • -library:链接名为 library 的库文件

  • -D macro:通过命令行定义宏,可以被源码中的 #ifdef 识别,相当于C语言中的 #define macro

  • -Wall:发生警告时取消编译

  • -Werror:发生警告时取消编译

  • -w:禁止所有报警

  • -pedantic:必须严格符合 ANSIC 标准

  • -m:指定架构生成代码。默认在 64 位机器上生成64 位代码,但指定 -m32 后会生成32位机器的汇编代码

gdb

参考:https://www.cnblogs.com/skyofbitbit/p/3672848.html

gdb 是个类似 shell 的交互调试程序,可以在调试指定程序的时候输入命令(设置断点、查看变量、单步调试等)。在 GDB 中执行 help 命令看查看帮助文档。

GDB 中的命令可以分为八类:别名(aliases)、断点(breakpoints)、数据(data)、文件(files)、内部(internals)、隐含(obscure)、运行(running)、栈(stack)、状态(status)、支持(support)、跟踪点(tracepoints)和用户自定义(user-defined)。

跟 gcc 的关系

要使用 gdb 调试可执行文件,需要编译的时候通过 -g 选项添加调试信息。

开始和退出 gdb 调试

开始调试:

  • gdb program:最常用的用 gdb 开始调试的方式
  • gdb program core:用 gdb 查看 core dump 文件,跟踪程序core的原因
  • gdb program pid:用 gdb 调试已经开始运行的程序,指定 pid 即可

退出调试:
quit 或者 q 命令。

命令

断点类

gdb 支持三类断点,用法都类似:

  • Breakpoint:让程序执行到某个特定的地方停止运行
  • Watchpoint:让程序在某个表达式的值发生变化的时候停止运行,达到‘监视’该表达式的目的
  • Catchpoint:让程序在发生某种事件的时候停止运行,比如C++中发生异常事件,加载动态库事件

设置断点

通过 break 命令可以设置断点,支持的参数有:行号、函数名、文件名+行号、文件名+函数名、当前行的前后偏移量、程序的地址。

a. breakfunction: 在函数funtion入口处设置breakpoint

b. break +offset:在程序当前停止的行向前offset行处设置breakpoint

c. break –offset:在程序当前停止的行向衙offset行处设置breakpoint

d. breaklinenum: 在当前源文件的第linenum行处设置breakpoint

e. breakfilename:linenum: 在名为filename的源文件的第linenum行处设置breakpoint

f. breakfilename:function: 在名为filename的源文件中的function函数入口处设置breakpoint

g. break *address:在程序的地址address处设置breakpoint

设置条件断点

设置单次断点

tbreak 命令用来设置单次断点,使用后自动删除。

根据正则表达式设置断点

rbreak regex 会在在所有符合正则表达式 regex 的函数处设置断点。

查看断点

info breakpoints [n]:查看第n个断点的相关信息,如果省略了 n 则显示所有断点的信息。

删除断点

clear:清除当前栈帧 stack frame 中下一条指令之后的所有断点
clear function 或 clear filename:function:清除函数 function 入口处的断点
clear linenum 或 clear filename:linenum:清除 linenum 行处的断点
delete [breakpoints] [range…]:删除由range指定的范围内的断点。range范围是指断点的序列号的范围

启用、禁用断点

disable [breakpoints] [range…]:禁用由range指定的范围内的断点
enable [breakpoints] [range…]:启用由range指定的范围内的断点
enable [breakpoints]once [range…]:只启用一次由range指定的范围内的断点,等程序停下来后,自动设为禁用
enable [breakpoints]delete [range…]:启用range指定的范围内的断点,等程序停下来后,这些断点自动被删除

在断点后添加命令

设置第 bnum 个断点执行的命令,不指定 bnum 时默认是 commands 命令上面的最后一个断点:

commands [bnum]
command-list...
end

取消:

commands [bnum]
end

示例,当x>0时,在foo函数处停下来,然后打印出x的值,然后继续运行程序:

break foo if x > 0
commands
silent
printf "x is %d\n", x
continue
end

监控断点

watch expr: 设置写watchpoint,当应用程序写expr,修改其值时,程序停止运行
rwatch expr: 设置读watchpoint,当应用程序读表达式expr时,程序停止运行
awatch expr: 设置读写watchpoint, 当应用程序读或者写表达式expr时,程序都会停止运行

捕获事件

catch event 命令使用后,在事件 event 发生的时候,程序停止运行。常用事件有:
1)throw: C++抛出异常
2)catch: C++捕捉到异常
3)exec: exec被调用
4)fork: fork被调用
5)vfork: vfork被调用
6)load:加载动态库
7)loadlibname: 加载名为libname的动态库
8)unload:卸载动态库
9)unloadlibname: 卸载名为libname的动态库
10)syscall [args]:调用系统调用,args可以指定系统调用号,或者系统名称

数据和代码

list 命令打印源码(缩写为l)

(1)list linenum: 打印当前文件中第linenum行周围的源代码
(2)list function: 打印function函数周围的源代码
(3)list:在上一次使用list命令的基础上,再多打印一些源代码
(4)list -:打印和上一次使用list命令一样的源代码
(5)set listsizecount: 设置list命令显示源代码的行数
(6)show listsize:查看list命令显示

print 命令打印数据

(1)printexpr: 打印表达式expr的值
(2)print /f expr:以f指定的格式打印表达式expr的值
(3)print:打印上一次打印的表达式的值
(4)print /f:以f指定的形式打印上一次打印的表达式的值
print支持的格式有:x-16进制整数,d-10进制整数,u-10进制无符号整数,o-8进制整数,t-2进制整数,a-地址形式整数,c-字符常量整数,f-浮点数

display 命令自动打印

(1)display /f expr|addr:以f为格式,打印expr或者addr
(2)undisplay dnums,delete display dnums:删除第dnums个display点
(3)disable display dnums:禁用第dnums个display点
(4)enable display dnums:启用第dnums个display点
(5)info display:查看所有的display点

打印选项:

set printfield: 打开field选项
set printfield on: 打开field选项
set printfield off: 关闭field选项
show printfield: 查看field选项的打开、关闭情况
(1)set print array:以一种比较好看的方式打印数组,缺省是关闭的
(2)set print elementsnum-of-elements:设置GDB打印数据时显示元素的个数,缺省为200,设为0表示不限制(unlimited)
(3)set print null-stop:设置GDB打印字符数组的时候,遇到NULL时停止,缺省是关闭的
(4)set print pretty:设置GDB打印结构的时候,每行一个成员,并且有相应的缩进,缺省是关闭的
(5)set print object:设置GDB打印多态类型的时候,打印实际的类型,缺省为关闭
(6)set print static-members:设置GDB打印结构的时候,是否打印static成员,缺省是打开的
(7)set print vtbl:以漂亮的方式打印C++的虚函数表,缺省是关闭的

查看寄存器:

(1)info registers:查看当前桢中的各个寄存器的情况
(2)info registersregname: 查看指定的寄存器

调用栈 Call Stack

查看调用栈信息

backtrace:显示程序的调用栈信息,可以用bt缩写
backtracen:显示程序的调用栈信息,只显示栈顶n桢(frame)
backtrace -n:显示程序的调用栈信息,只显示栈底部n桢(frame)
set backtrace limitn:设置bt显示的最大桢层数
where,info stack:都是bt的别名,功能一样

选择某一桢进行查看:

framen: 查看第n桢的信息
frameaddr: 查看pc地址为addr的桢的相关信息
upn: 查看当前桢上面第n桢的信息
downn: 查看当前桢下面第n桢的信息

frame信息内容:

  • 用backtrace、framen或者frameaddr得到的简要信息内容:
(1)桢序号(Frame number)
(2)函数名
(3)Program counter(除非set print address off)(在程序当前执行到的那一桢,PC不会被显示)
(4)源代码文件名和行号
(5)函数的参数名和传入的值
  • 用info frame、info framen或者info frameaddr得到的详细的信息内容:
(1)当前桢的地址
(2)下一桢的地址
(3)上一桢的地址
(4)源代码所用的程序的语言(c/c++)
(5)当前桢的参数的地址
(6)当前相中局部变量的地址
(7)PC(program counter)
(8)当前桢中存储的寄存器

其他信息

info args:查看当前桢中的参数
info locals:查看当前桢中的局部变量
info catch:查看当前桢中的异常处理器(exception handlers)

你可能感兴趣的:(Linux,C/C++)