C++编译过程及动静态库

从源代码到可执行程序

四步:预处理 编译 汇编 链接

预处理
1、宏定义展开
2、预编译命令的处理如#if #ifdef一类的命令;
3、展开#include引用的头文件,如:#include"stdio.h",会把sdio.h中所有代码合并到main.c

4、去掉注释

gcc -E main.c -o main.i

编译:
将c++代码翻译成汇编代码,把预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码

gcc -S main.i -o main.s // main.s也是文本文件

汇编:
将汇编文件翻译成机器码,这一步产生的文件叫做目标文件,是二进制格式

as main.s -o main.o

链接:
将多个目标文件与外部符号链接得到可执行的二进制文件

gcc main.o -o main

查看符号表的几种方式:
nm 目标文件
objdump -t 目标文件
readelf -s 目标文件
strings 目标文件

动态库和静态库

静态链接:
在编译阶段直接把静态库加入到可执行文件中去

gcc -c func.c
ar crsv libfunc.a func.o

使用静态库

gcc -o main main.c -lfunc -L./

动态链接:
是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应的动态库加载到内存中去

gcc -fPIC -c func.c
gcc -shared -o  libfunc.so func.o  // func可能会使用到其他库,指定-shared,使得优先链接动态库

使用动态库
例:比如main.c用到了func

gcc -o main main.c -lfunc -L./     // -l指定要链接的库,-L指定链接库所在的路径
export  LD_LIBRARY_PATH=./
./main

注意:执行时需要指定搜索连接库的路径,可执行程序运行时会先后搜索环境变量LD_LIBRARY_PATH设置的路径-搜索/etc/ld.so.cache文件列表-搜索/lib和/usr/lib目录,找到需要使用的库文件载入内存。
1、搜索环境变量LD_LIBRARY_PATH设置的路径 – 可以通过export LD_LIBRARY_PATH设置库文件路径
2、搜索/etc/ld.so.cache文件列表 – 将库所在的路径方式添加到/etc/ld.so.conf中,然后执行ldconfig即可更新ld.so.cache
3、搜索/lib和/usr/lib目录 – 将库文件拷贝到该目录下

静态库和动态库的区别优劣:
1、gcc/g++在链接时既有动态库又有静态库,会优先选择动态库,可以通过-static优先链接静态库
2、可执行文件大小不一样 - - - 静态链接的可执行文件要比动态链接的可执行文件要大得多
3、占用磁盘大小不一样 - - - 静态库因为会被拷贝N份到各自的可执行程序中,而动态库各个可执行程序可以共享一份,因此使用静态库占用的磁盘空间相对比动态库要大。
4、依赖不一样 - - - 静态链接在链接时将静态库加入到了可执行程序中,因此静态链接后生成的可执行程序运行时不依赖静态库,删除静态库依然可以执行。
5、扩展性与兼容性不一样 - - - 如果静态库中某个函数的实现变了,那么可执行文件必须重新编译,而对于动态链接生成的可执行文件,只需要更新动态库本身即可,不需要重新编译可执行文件。正因如此,使用动态库的程序方便升级和部署。
6、加载速度不一样 - - - 由于静态库在链接时就和可执行文件在一块了,而动态库在加载或者运行时才链接,因此,对于同样的程序,静态链接的要比动态链接加载更快。所以选择静态库还是动态库是空间和时间的考量。但是通常来说,牺牲这点性能来换取程序在空间上的节省和部署的灵活性时值得的。

参考资料:
https://zhuanlan.zhihu.com/p/71372182
https://www.cnblogs.com/skynet/p/3372855.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值