GNU编译工具使用

安装

1
2
3
4
5
6
7
8
sudo apt update
# 通过以下命令安装编译器和调试器
sudo apt install build-essential gdb

# 查看版本号
gcc --version
g++ --version
gdb --version

gcc/g++基本用法

1
2
3
4
gcc filename -o outputfileName

# gdb支持
gcc filename -g -o outputfileName

编译过程

预处理

生成**.i** 文件

1
2
# -E 选项指示编译器仅对输入文件进行预处理
g++ -E test.cpp -o test.i

编译

生成**.s** 文件

1
2
3
# -S 编译选项告诉 g++ 在为 C++ 代码产生了汇编语言文件后停止编译
# g++ 产生的汇编语言文件的缺省扩展名是 .s
g++ -S test.i -o test.s

汇编

生成**.o** 文件

1
2
3
# -c 选项告诉 g++ 仅把源代码编译为机器语言的目标代码
# 缺省时 g++ 建立的目标代码文件有一个 .o 的扩展名。
g++ -c test.s -o test.o

链接

生成可执行 文件

1
2
# -o 编译选项来为将产生的可执行文件用指定的文件名
g++ test.o -o test

重要参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-E 预处理指定的源文件,不进行编译
-S 编译指定的源文件,但是不进行汇编
-c 编译、汇编指定的源文件,但是不进行链接
[file2] -o [file1] 将文件 file2 编译成可执行文件 file1,指定输出文件名
-I directory 指定 include 包含文件的搜索目录
-g 在编译的时候,生成调试信息,该程序可以被调试器调试
-D 在程序编译的时候,指定一个宏
-w 不生成任何警告信息
-Wall 生成所有警告信息
-O[n] n的取值范围:0~3,编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-l 在程序编译的时候,指定使用的库
-L 指定编译的时候,搜索的库的路径
-fPIC/fpic 生成与位置无关的代码
-shared 生成共享目标文件,通常用在建立共享库时
-std 指定C方言,如:-std=c++11

静态库与动态库

  • 库文件是计算机上的一类文件,可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。
  • 库是特殊的一种程序,只是库不能单独运行。
  • 库文件有两种,静态库和动态库(共享库),区别是:静态库在程序的链接阶段被复制到了程序中;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。
  • 库的好处:代码保密、方便部署和分发。

静态库

1
2
3
4
5
6
7
8
9
10
11
命名规则:
◆ Linux : libxxx.a
lib : 前缀(固定)
xxx : 库的名字,自己起
.a : 后缀(固定)
◆ Windows : libxxx.lib

制作:
# gcc 获得.o 文件
# 将.o 文件打包,使用 ar 工具(archive)
ar rcs libxxx.a xxx.o xxx.o

动态库

1
2
3
4
5
6
7
8
9
10
11
12
13
命名规则:
◆ Linux : libxxx.so
lib : 前缀(固定)
xxx : 库的名字,自己起
.so : 后缀(固定)
在Linux下是一个可执行文件
◆ Windows : libxxx.dll

制作:
# gcc 得到 .o 文件,得到和位置无关的代码
gcc -c –fpic/-fPIC a.c b.c
# gcc 得到动态库
gcc -shared a.o b.o -o libcalc.so

gdb调试

功能:

  • 设置断点(断点可以是条件表达式)
  • 使程序在指定的代码行上暂停执行,便于观察
  • 单步执行程序,便于调试
  • 查看程序中变量值的变化
  • 动态改变程序的执行环境
  • 分析崩溃程序产生的core文件

指令可以简写,是第一个字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 启动
gdb outputfileName

# 退出
quit

# GDB 使用帮助
help

# 查看当前文件代码
list/l (从默认位置显示)
list/l 行号 (从指定的行显示)
list/l 函数名(从指定的函数显示)

# 设置断点
b/break 行号
b/break 函数名
b/break 文件名:行号
b/break 文件名:函数
# 删除断点
d/del/delete 断点编号
# 设置断点无效
dis/disable 断点编号
# 设置断点生效
ena/enable 断点编号
# 设置条件断点(一般用在循环的位置)
b/break 10 if i==5

# 运行
start(程序停在第一行)
run(遇到断点才停)

# 暂停后继续,到下一个断点停
c/continue

# 通过命令'next' 和'step' 逐行运行程序。
# Next 将控件严格保持在当前范围内
n/next # 向下执行一行代码(不会进入函数体)

# 向下单步调试(遇到函数进入函数体)
s/step
finish(跳出函数体)

# 变量操作
p/print 变量名(打印变量值)
ptype 变量名(打印变量类型)

# 修改变量
set <var> = <value>

# 设置观察点,每当发生更改时,程序都会暂停并为您提供更改的详细信息。
# 只能在变量处于范围内时为其设置观察点
watch <var>

参考资料


GNU编译工具使用
http://example.com/2022/07/23/GNU编译工具使用/
作者
ZYUE
发布于
2022年7月23日
更新于
2022年7月31日
许可协议