Linux入门3(程序的编译与调试 静态库和动态库)

程序的编译与调试

编译连接过程

计算机的五大部件
运算器 控制器 存储器 输入设备 输出设备
指令,二进制的机器指令,程序由一条条的指令构成
机器指令 汇编助记符 高级语言
0110 add a+b
1010 mov a=b

预编译

删除注释,替换宏定义,将include 文件加入展开,代码量会急剧增加

gcc -E main.c -o main.i

编译

将高级语言转换为汇编助记符(即汇编语言), 会进行语法的检测,代码会急剧减少,

gcc -S main.i -o main.s

汇编

从汇编助记符翻译成机器(二进制)指令,Linux平台的可执行程序格式为ELF

gcc -c main.s -o main.o

链接

链接一些库函数,因为main.o 是一个模块

gcc main.o -o main

可以一步完成,但是如果有的.c程序没有主函数,就不能一步生成可执行程序,可以先生成-o 编译成二进制文件

gcc -o main main.c

可以用命令将源文件生成.o二进制文件

gcc -c add.c -o add.o

后面可以省略

gcc -c add.c 

makefile和make

安装make

如果没有安装make,安装make

sudo apt install make

Makefile文件里面的内容

all : main

main : main.o add.o max.o
	gcc -o main main.o add.o max.o

main.o : main.c
	gcc -c main.c

add.o : add.c
	gcc -c add.c

max.o : max.c
	gcc -c max.c

clean :
	rm -rf main *.o

rm -rf main *.o 删除main和后缀是.o的文件

使用

直接make 就执行了Makefile文件里面的命令,除了clean
make clean 就可以清除 rm -rf main *.o

gdb调试

生成具有调试信息的main,该程序是dubag版本,不加-g 就是release版本,gdb调试的是可执行程序

生成可以调试的可执行文件

gcc -o main main.c add.c max.c -g
gcc -g -o test test.c

常用调试命令

查看代码 l list
加断点 b break
查看断点信息 info break
查看函数堆栈 bt
运行 r run
查看变量的值 p print
单步执行 n next
一直执行,直到遇见断点 c continue
进入函数 s
跳出函数 f finish
停止调试q quit
进入帮助手册 help
查看以该字符开头的所有命令 按两次tab
bt 显示函数调用栈
多进程中,跟踪子进程:set follow-fork-mode child 默认跟踪父进程 可以改成子进程
多线程中,
查看进程堆栈 pstack+pid

用gdb调试多进程程序

1.单独调试子进程 用attach 4183 将子进程4183附加2.到gdb调试器
2.使用调试器选项:set follow-fork-mode child 默认跟踪父进程 可以改成子进程

用gdb调试多线程程序

A 查看线程信息 info threads 有*就是当前线程
B 切换到指定线程 thread id
set scheduler-locking [off]on|step]。调试多线程程序时,默认除了被调试的线程在执行外,其他线程也在继续执行,但有的时候我们希望只让被调试的线程运行。这可以通过这个命令来实现。该命令设置schedulcr-locking 的值: off表示不锁定任何线程,即所有线程都可以继续执行,这是默认值;on表示只有当前被调试的线程会继续执行;step表示在单步执行的时候,只有当前线程会执行。

Linux 系统上的库文件生成与使用

库文件定义

库是一组预先编译好的方法的集合。Linux系统存储的库的位置一般在:/lib 和 /usr/lib。
在 64 位的系统上有些库也可能被存储在/usr/lib64 下。库的头文件一般会被存储在
/usr/include 下或其子目录下。
库有两种,一种是静态库,其命令规则为 libxxx.a,一种是共享库,其命令规则为 libxxx.so

静态库的生成与使用

静态库的生成

其中“foo.h”中是函数的声明,“add.c”和“max.c”是函数的定义
第一步:先将需要生成库文件的所有“.c“文件编译成“.o”文件

gcc -c add.c
gcc -c max.c

第二步:使用 ar 命令将第一步编译的所有”.o”文件生成静态库

ar crv libfoo.a add.o max.o

◼ c 是创建库
◼ r 是将方法添加到库中
◼ v 显示过程

静态库的使用

gcc -o main main.c -L. -lfoo

◼ -L 指定库的存储路径
◼ -l 指定库的名称(不需要前面的‘lib’和扩展名‘.a’)
可以将静态库放到指定的目录下,就不需要用来-L.指定位置,但是,-lfoo必不可少

因为静态库是链接的时候就放在了可执行程序里,所以,将库删除,上次生成的可执行程序照样可以运行

如果将foo.h制动到

mv foo.h /usr/include

引用的时候可以include<foo.h>,否则用inlcude “foo.h”

动态库的生成与使用

动态库的生成

其中“foo.h”中是函数的声明,“add.c”和“max.c”是函数的定义

第一步:先将需要生成库文件的所有“.c“文件编译成“.o”文件

gcc -c add.c
gcc -c max.c

第二步:使用 gcc 命令将第一步编译的所有”.o”文件生成共享库

gcc -shared -fPIC -o libfoo.so add.o max.o

动态库的使用

因为系统默认只会去存储库的标准位置(/lib 或/usr/lib )加载,而不会在当前位置寻找。所以将库拷贝到/usr/lib 下,再执行程序,就可以成功。

cp libfoo.so /usr/lib
gcc -o main main.c -L. -lfoo

这里也可以不用写指定位置,-L.指定位置,但是,-lfoo必不可少

gcc -o main main.c  -lfoo

可以通过 ldd 命令查看可执行程序使用了哪些共享库

也可以通过设置环 境变量来指定加载库的路径

打印该变量的值

echo $LD_LIBRARY_PATH 

设置环境变量

LD_LIBRARY_PATH=.
export LD_LIBRARY_PATH

总结一下,就是对于动态库,要么将动态库放在标准路径下,要么设置环境变量(一般用作测试)

静态库和共享库的区别

静态库在链接时将用到的方法包含到最终生成的可执行程序中,而共享库不包含,只做标记,在运行程序时,才动态加载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值