gcc下静态库和动态库的生成及使用

1. 静态库与动态库简介

gcc详解: GCC编译过程及基本命令总结_天涯明月刀的博客-CSDN博客_gcc编译命令

gcc的编译过程分为预处理、编译、汇编、链接。其中链接就是将所有目标文件(.o)与库文件中的函数链接到一起生成可执行文件。且链接分为静态链接和动态链接,静态链接使用的是静态库,动态链接使用的动态库。

  • 静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。链接器将函数的代码从其所在地(不同的目标文件或静态链 接库中)拷贝到最终的可执行程序中。为创建可执行文件,链接器必须要完成的主要任务是:符号解析(把目标文件中符号的定义和引用联系起来)和 重定位(把符号定义和内存地址对应起来然后修改所有对符号的引用)。
  • 动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。
  • 链接动态库和静态库的路径可能有重合,所以如果在路径中有同名的静态库文件和动态库文件,gcc 链接时默认优先选择动态库,可以指定 gcc 选项-static,该选项会强制使用静态库进行链接。

动态库与静态库的概念:

  • 如果要将多个.o目标文件生成一个库文件,则存在两种类型的库,一种是静态库,另一种是动态库。
  • 在 windows 中静态库是以 .lib 为 后缀的文件,共享库是以 .dll 为 后缀的文件。在 linux 中静态库是以 .a为后缀的文件,共享库是以 .so 为后缀的文件。
  • 静 态 库 和 动 态 库 的 不 同 点 在 于 代 码 被 载 入 的 时 刻 不 同 。 静 态 库 的 代 码 在 编 译 过 程 中 已 经 被 载 入 可 执 行 程 序 , 因 此 体 积 较 大 。 共 享 库 的 代 码 是 在 可 执 行 程 序 运 行 时 才 载 入 内 存 的 , 在 编 译 过 程 中 仅 简 单 的 引 用 , 因 此 代 码 体 积 较 小 。 在 Linux 系 统 中 , 可 以 用 ldd 命 令 查 看 一 个 可 执 行 程 序 依 赖 的 共 享 库。
  • 如果一个系统中存在多个需要同时运行的程序且这些程序之间存在共享库,那么采用动态库的形式将更节省内存。

2. 编写程序

安装gcc: sudo apt install gcc

所有程序皆使用 vim 编写 一般模式下输入 :set nu 显示行号 :set nonu 取消行号

  1. 编写 sub1.c
//计算a除以b的结果
float x2x(int a,int b)
{
        return (float)a/b;
}
  1. 编写sub.2.c
//计算a加上b的结果
int x2y(int a,int b)
{
        return a+b;
}
  1. 编写 sub.h
#pragma once
#include <stdio.h>

float x2x(int a,int b);  //计算a除以b的结果
int x2y(int a,int b);     //计算a加上b的结果
  1. 编写 main.c
#include "sub.h"
  
int main()
{
        int a=10,b=3;
        printf("相除结果为:%.5f\n",x2x(a,b));  //调用函数x2x,实现计算 a%b 并保留5位小数
   	    printf("相加结果为:%d\n",x2y(a,b));  //调用函数x2y,实现计算 a+b
        return 0;
}

3. 静态库的生成及使用

  1. 将文件sub1.c与sb2.c编译生成目标文件。 gcc -c sub1.c sub2.c

image-20211003175141546

  1. 由目标文件生成静态库。

静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将 创建的静态库名为 sub,则静态库文件名就是 libsub.a。在创建和使用静态库时, 需要注意这点。创建静态库用 ar 命令。

ar -crv libsub.a sub1.o sub2.o

image-20211003175625261

  1. 使用静态库生成可执行文件

gcc main.c libsub.a -o main.a 生成可执行文件main.a

其它生成方法: Linux基础——gcc编译、静态库与动态库(共享库)_daidaihema的博客-CSDN博客_gcc 编译静态库

image-20211003180626370

4. 动态库的生成及使用

目标文件已在上方已经生成过了。

  1. 由目标文件生成动态库。

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其 文件扩展名为.so。例如:我们将创建的动态库名为 sub,则动态库文件名就是 libsub.so。用 gcc 来创建动态库。

gcc -shared -fPIC -o libsub.so sub1.o sub2.o

image-20211003181135960

  1. 使用动态库生成可执行文件

gcc main.c libsub.so -o main.so 生成可执行文件 main.so

image-20211003182319193

发现错误,找不到动态库文件 libsub.so。

解决办法:程序在运行时, 会在/usr/lib 和/lib 等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。因此我们将文件 libsub.so 复制到目录/usr/lib 中即可。

mv libsub.so /usr/lib 需要root权限

image-20211003182857230

5. 静态库与动态库生成的可执行文件大小比较

使用size查看大小。

text: 已编译程序的指令代码段

data: 已初始化的 C 程序全局变量和静态局部变量

bss:未初始化的 C 程序全局变量和静态局部变量

image-20211003183241574

占用空间大小
image-20211003184210431

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值