Linux 学习笔记3 编译与调试之动态库静态库与GDB调试

Linux 学习笔记3 动态库静态库与gdb调试

对于.c格式的c文件,可采用gcc编译,而对于.cc或.cpp的文件可采用g++进行编译.

编译常用选项:
-c 表示编译源文件
-o 表示输出目标文件
-g 表示在目标文件中产生调试信息,用于 gdb 调试
-D 编译时将宏定义传入进去
-Wall 打开所有类型的警告
gcc -v 查看gcc的版本
-E 表示预处理
-S 表示编译

  1. gcc编译过程:预编译->编译->汇编->链接
    Linux 学习笔记3 编译与调试之动态库静态库与GDB调试
    Linux编译过程

step1:预处理,包含头文件,展开宏定义
gcc -E test.c -o test.i
step2:编译,将C语言——>汇编语言
gcc -S test.i -o test.s
step3:汇编:汇编语言——>机器语言
as test.s -o test.o
step4:链接
gcc test.c -o test

  1. gcc库选项

Linux 学习笔记3 编译与调试之动态库静态库与GDB调试

gcc常用库选项Linux 学习笔记3 编译与调试之动态库静态库与GDB调试
tips:查找动态库 在lib 中 find . -name “.so

  1. 静态库与动态库

3.1
静态库时目标文件.a的归档文件(格式为libname.a)
如:add(加法函数)则为libadd.a
如果在编译某个程序时链接静态库,则链接器将会搜索静态库并直接拷贝到该程序的可执行二进制文件 到当前文件中。

动态库(格式为libname.so),编译时不会被链接到目标代码中,而是在程序运行时才被载入。

3.2

动态库创建(以add函数为例)

step1:gcc -fPIC -Wall -c add.c
step2:gcc -shared add.o -o libadd.so
step3链接库:gcc main.c -ladd

Linux 学习笔记3 编译与调试之动态库静态库与GDB调试

静态库创建

step1:gcc -c add.c //编译add.c源文件生成add.o目标文件
step2:ar crsv libadd.a add.o //对目标文件*.o进行归档,生成lib*.a则生成静态库libadd.a
step3:gcc main.c -ladd //编译main.c时,链接静态库

Linux 学习笔记3 编译与调试之动态库静态库与GDB调试
动态库与静态库比较
动态库只有在执行时才被链接使用,且一个动态库可被多个程序使用
静态库会整合到程序中在执行时不用加载,静态库容易部署但是静态库会使得程序臃肿而且难以升级。
亦或是
区别:
1编译时静态库直接编译进可执行程序,会造成可执行程序比较臃肿而动态库没有编译进可执行程序
2执行时可执行程序依赖于动态库,动态库的路径不能被改变也不能被删除

注:ldd是list, dynamic, dependencies的缩写, 意思是, 列出动态库依赖关系。 当然, 你也可以用ldd --help或者man ldd来看其用法

  1. 程序调式 gdb

采用-g打开调试选项,如:gcc -g main.c; gdb a.out

常用gdb命令:

命令 作用
l list显示代码
r run 运行
b 6 在第6行设置断点
n next下一步进入函数,相当于vs的F10
s 单步进入函数,相当于windows下的F11
p a 打印a的值
p &a 打印a的地址
c 运行到最后 continue
q 退出 quit
info b 查看所设置的断点
d 1 删除第一个断点
disable 3 使3号断点失效
enable 5 使5号断点生效
set args 3 4 设置运行时的参数为3,4
show args 显示参数
path dir 设定程序运行的路径
show paths 查看程序运行的路径
x /12xb &i 以16进制的方式查看12字节的变量 i 的地址
backtrace(bt) 调用堆栈

tips:针对段错误(segmentation fault)
定位错误的方法为:
step1 :gcc -g main.c //重新添加-g参数编译
step2:ulimit -a 查看(core file size)
令ulimit -c unlimited //打开core限制
再运行一次可执行文件,则会产生一个core文件
setp3:重新运行程序
step4:gdb a.out core 则会打印程序在哪一行崩溃(即还原事故现场)