目录
[第四章 GDB调试工具](#第四章 GDB调试工具)
[4.4 gdb的使用](#4.4 gdb的使用)
[第五章 makefile工程管理工具](#第五章 makefile工程管理工具)
第四章 GDB调试工具
4.1gdb的作用
代码调试工具,可以帮助调试代码
替代刚入门时使用一句一printf的调试方法,来找到代码出问题的地方
4.2调试代码的流程
测试:发现问题
定位:通过标志提示或删除功能,定位出问题的大概位置
修改:分析问题,改正问题
测试:验证结果
4.3gdb的安装
cpp
sudo apt-get install gdb
在线安装gdb
4.4 gdb的使用
4.4.1准备工作
gdb调试的代码,需要使用gcc的-g参数生成可执行文件的gdb
cpp
gcc -g main.c -o maingdb
4.4.2启动gdb
常规启动:
cpp
gdb ./maingdb
主函数传参启动:
方法一:
cs
gdb --args ./maingdb 参数1 参数2...
方法二:在开启gdb之后,启动程序之前:
cs
set args 参数1 参数2...
方法三:在开启gdb之后,启动程序之前:
cs
run 参数1 参数2 ...
4.4.3退出gdb
退出gdb指令:q
4.4.4显示代码指令:list 或 l(小写 L)
cs
l n #显示第 n 行附近的代码
例如查看12行附近的代码
4.4.5连续运行指令:run或r
代码从头开始执行,一直到结束停止,或者运行到断点位置暂停
遇到主函数传参(例如计算器程序中):r 10 + 20
argv[0]==r
argv[1]==10
argv[2]==+
argv[3]==20
或者:在传参后
4.4.6设置断点指令:break或b
cs
b n#在第n行设置断点
4.4.7查看断点指令
cs
info b
这里可以主要关注Enb列和What列
4.4.8失能断点指令:disable
失能只是不生效了,并没有删除
cs
disable 断点编号
4.4.9使能断点指令:enable
让断点失能后,就有恢复的需要
cs
enable 断点编号
4.4.10删除断点指令clear或delete
cs
clear 断点行号
delete 断点编号
试一下clear:
试一下delete:
4.4.11 继续运行指令:cont 或 c
4.4.12 打印变量当前的值指令:print
cs
print 变量名 #打印变量的值
4.4.13 单步调试启动指令:start
自动调用上一次运行时传入的参数
4.4.14 单步执行指令: n 或 s
n(next):遇到子函数,不会进入子函数内部,以函数为单位执行
s(step):遇到子函数,会进入子函数内部,以语句为单位执行
常用操作:遇到库函数按 n,不能进入,否则会卡死 遇到普通函数按 s
第五章 makefile工程管理工具
5.1makefile的作用
工程管理工具:名字为makefile的文件
将准备在终端中执行的指令,写入到该文件中(按照规定语法格式写)
5.2makefile的运行
若执行的文件名为makefile:直接在终端键入make,即可自动执行makefile文件中写入的指令
若执行的文件未命名未makefile:终端键入make -f 文件名
5.3make的安装
sudo apt-get install make
在线安装make工具
5.4makefile的编写方法
编写思想:目标和依赖的关系。
首先构思如何通过依赖生成目标,整个过程中一切指令都是为了生成最终目标
5.5makefile的语法
5.5.1注释
#注释
5.5.2 语法一
makefile中不能键入空格,只能键入Tab。否则无效。
cs
目标:依赖
命令 #通过依赖生成目标的命令
5.5.3 语法二
cs
目标:
命令 #可以直接执行的命令,不一定要得到目标
伪目标:没有依赖的目标
执行伪目标的指令:make 伪目标
5.5.4 变量
cs
变量名=值 #定义变量
$(变量名) #引用变量名对应的值
vim 底行模式:字符串自主选择替换--- :%s/gcc/$(cc)/gc
5.5.5 特殊变量
$@ 代表目标
$^ 代表所有依赖
$< 代表所有依赖中的第一个
% makefile 中的通配符
经过变量替换后,代码可以变成,除了计算机,大家都一眼看不懂的样子。
5.6makefile使用示例
这里我依然使用计算器的模块程序
首先实现静态库封装
cs
inc=./inc
src=./src
out=./output
libpath=./lib
libname=static #以上都是变量替换
main:main.c $(libpath)/lib$(libname).a
gcc $< -l$(libname) -L$(libpath) -o $@ -I$(inc)
@echo 编译完成
./main 1 + 1
$(libpath)/lib$(libname).a: $(out)/add.o $(out)/jian.o
ar -rc $@ $^
@echo 静态库制作完成
$(out)/%.o:$(src)/%.c
gcc -c $< -o $@ -I$(inc)
clean:
rm $(out)/*.o main $(libpath)/lib$(libname).a
其次,实现动态库封装
cs
main:main.c ./lib/libmove.so
sudo mv ./lib/libmove.so /usr/lib
gcc main.c -lmove -I./inc -o main
./main 1 + 1
./lib/libmove.so:./output/add.o ./output/jian.o
gcc -shared -fpic -o $@ $^
./output/%.o:./src/%.c
gcc -c $< -o $@ -I./inc
clean:
rm ./lib/libmove.so ./output/*.o main
整个工程管理有点倒置执行的意思,但总共执行那编译四步、编译两步,理清执行顺序就可以。