GCC链接静态库和动态库详解

news/2024/8/26 21:49:10 标签: linux, gcc, 嵌入式

文章目录

1. 静态库和动态库

2. 静态库链接

3. 动态库链接


1. 静态库和动态库

链接(linking)是编译过程的最后一步,它将多个目标文件( .o 文件)和库文件结合在一起,生成一个可执行的二进制文件。链接的主要任务是解析符号引用,合并代码和数据段,并处理重定位信息。

对于整个gcc的编译过程命令解析查看下面这篇文章:

gcc命令以及GDB调试选项-CSDN博客

静态库和动态库是根据链接时机的不同来划分的,它们主要区别在于库文件在程序运行中的加载和使用方式。

静态库

静态库在编译和链接阶段就会被包含在可执行程序里,生成的可执行文件已经内嵌了所有的库代码,具备独立运行的能力。具体特点如下:

  1. 内嵌到可执行文件中:静态库的代码在编译时会被复制到最终的可执行文件中,程序运行时不需要依赖外部库文件。
  2. 独立性强:生成的可执行文件独立,不依赖外部库,方便分发和部署。
  3. 性能较好:由于不需要在运行时加载库,程序启动速度较快。
  4. 更新复杂:如果库代码有bug或需要升级,所有使用该库的程序都需要重新编译和链接,维护工作量较大。
  5. 空间浪费:每个使用静态库的可执行文件中都会包含一份库的代码,如果多个程序都使用同一个静态库,会导致空间浪费。

动态库

动态库在程序运行时才被加载,多个程序可以共享一份动态库,从而节省存储空间。具体特点如下:

  1. 运行时加载:动态库在程序运行时根据需要加载,不会在编译时被复制到可执行文件中。
  2. 共享性高:多个程序可以共享同一个动态库,节省内存和存储空间。
  3. 更新方便:如果动态库有bug或者需要升级,只需要替换新的库文件即可,不需要重新编译和链接使用该库的所有程序。
  4. 启动速度慢:由于在运行时需要加载库,程序启动速度相对较慢。
  5. 依赖性强:可执行文件运行时依赖外部的动态库文件,如果库文件缺失或版本不兼容,程序可能无法正常运行。

接下来创建三个文件 main.cadd.cadd.h 来讲解静态库链接和动态库链接的过程。

main.c

#include <stdio.h>
#include "add.h"

int main(int argc, char *argv[])
{
    printf("%d\n", add(10, 10));
    printf("%d\n", add(20, 20));
    return 0;
}

add.c

#include "add.h"

int add(int a, int b)
{
    return a + b;
}

add.h

#ifndef __ADD_H
#define __ADD_H

int add(int a, int b);

#endif

2. 静态库链接

静态库的名字一般为 “libxxx.a”。利用静态库编译生成的可执行文件比较大,因为整个函数库的所有数据都被整合进了可执行文件中。

优点:

  1. 不需要外部函数库支持。
  2. 加载速度快。

缺点:

  1. 静态库升级时,程序需要重新编译。
  2. 多个程序调用相同库,静态库会重复载入内存,造成内存浪费。

静态库的制作步骤如下:

  1. 编译 add.c 文件为目标文件 add.o

    gcc add.c -o add.o -c
    
  2. 使用 ar 工具将目标文件 add.o 打包成静态库 libadd.a

    ar -rc libadd.a add.o
    

静态库的使用步骤如下:

1. 编译 main.c 文件,并链接静态库 libadd.a,生成可执行文件 output

gcc main.c -o output -ladd -L.
  • -L. 表示在当前目录(. 表示当前目录)中查找库。
  • -ladd 表示链接库名为 libadd.a(省略了前缀 lib 和后缀 .a)。

2. 运行生成的可执行文件 output

./output

运行结果: 

20
40
  • gcc add.c -o add.o -c:这条命令将 add.c 文件编译为目标文件 add.o
  • ar -rc libadd.a add.o:这条命令将目标文件 add.o 打包成静态库 libadd.a
  • gcc main.c -o output -ladd -L.:这条命令将 main.c 文件编译并链接静态库 libadd.a,生成可执行文件 output
    • -L. 选项用于指定库文件的搜索路径为当前目录。
    • -ladd 选项用于指定链接的库名为 libadd.a

静态库在编译期间被整合到可执行文件中,提供了加载速度快和独立性高的优点,但在库升级和内存利用方面存在一些缺点。

3. 动态库链接

动态库名字一般为 “libxxx.so”,又称共享库。动态库在编译时没有被编译进可执行文件,所以可执行文件比较小。程序运行时,操作系统帮我们找到库,并跟程序链接起来。

优点:

  1. 多个程序可以使用同一个动态库,节省内存。
  2. 库可以升级,而不需要重新编译应用程序。

缺点: 加载速度较慢,因为需要在运行时找到并加载库。

动态库的制作步骤如下:

1. 编译 lib.c 文件为动态库 libtest.so

gcc -shared -fPIC lib.c -o libtest.so

2. 将生成的动态库 libtest.so 复制到 /usr/lib 目录(需要超级用户权限):

sudo cp libtest.so /usr/lib/

动态库的使用步骤如下:

1. 编译 main.c 文件,并链接动态库 libtest.so,生成可执行文件 output

gcc main.c -L. -ltest -o output
  • -L. 表示在当前目录(. 表示当前目录)中查找库。
  • -ltest 表示链接库名为 libtest.so(省略了前缀 lib 和后缀 .so)。

2. 运行生成的可执行文件 output

./output

运行结果:

20
40
  • gcc -shared -fPIC lib.c -o libtest.so:这条命令将 lib.c 文件编译为动态库 libtest.so-shared 表示创建共享库,-fPIC 表示生成与位置无关的代码(Position Independent Code)。
  • sudo cp libtest.so /usr/lib/:这条命令将生成的动态库 libtest.so 复制到系统的库目录 /usr/lib 中。
  • gcc main.c -L. -ltest -o output:这条命令将 main.c 文件编译并链接动态库 libtest.so,生成可执行文件 output
    • -L. 选项用于指定库文件的搜索路径为当前目录。
    • -ltest 选项用于指定链接的库名为 libtest.so

动态库在编译时没有被编译进可执行文件,而是在程序运行时由操作系统加载,从而提供了节省内存和库可升级的优点,但在运行时加载速度较慢。


http://www.niftyadmin.cn/n/5558439.html

相关文章

mac如何合并pdf文件到一个文件 macpdf合并 Mac如何合并pdf文件

在数字化的今天&#xff0c;pdf文件因其跨平台、格式统一等优势&#xff0c;已经成为工作、学习和生活中不可或缺的文件格式。然而&#xff0c;当我们需要合并多个pdf文件时&#xff0c;可能会感到有些无从下手。本文将为你详细介绍几种简单实用的合并pdf的方法&#xff0c;让你…

sklearn基础教程:从入门到精通

文章目录 sklearn基础教程&#xff1a;从入门到精通一、sklearn简介二、安装与配置三、数据预处理数据导入数据清洗特征选择数据标准化与归一化 四、常用模型介绍与应用线性回归逻辑回归决策树支持向量机K近邻算法随机森林集成学习 五、模型评估与调优交叉验证网格搜索模型评估…

【Git 学习笔记】第七章 用 git hook 钩子、别名、脚本提升日常工作效率(上)

文章目录 第七章 用 Git 钩子、别名、脚本提升日常工作效率&#xff08;上&#xff09;7.1 在提交消息中应用分支描述信息7.2 创建提交消息的动态模板例一&#xff1a;设置为拒绝提交例二&#xff1a;拒绝 --amend 提交例三&#xff1a;在提交注释中插入外部网页的请求内容知识…

深度学习损失计算

文章目录 深度学习损失计算1.如何计算当前epoch的损失&#xff1f;2.为什么要计算样本平均损失&#xff0c;而不是计算批次平均损失&#xff1f; 深度学习损失计算 1.如何计算当前epoch的损失&#xff1f; 深度学习中的损失计算&#xff0c;通常为数据集的平均损失&#xff0…

智能家居安卓程序设计(二)

一 UI设计 主界面布局文件 设备界面 程序既支持语音输入也支持屏幕点击&#xff0c; 可以对着该程序 发出语音指令&#xff0c;如 打开电视&#xff0c;调节音量&#xff0c;调节频道等。 二、系统架构 硬件层 传感器&#xff1a;温度传感器、湿度传感器、光传感器、运动传感器…

FPGA二选一选择器

1、需求 使用XILINX的XC7A35TFFG484-2开发板&#xff0c;完成二选一选择器的设计。 2、分析 二选一选择器如下所示&#xff1a; 观察可知有三个输入端&#xff0c;一个输出端&#xff0c;其逻辑原理为&#xff1a;当sel为高电平时&#xff0c;outa&#xff0c;当sel为低电平…

vue3 学习笔记13 -- 生命周期和防抖节流

vue3 学习笔记13 – 生命周期和防抖节流 生命周期 创建周期&#xff08;Composition API&#xff09; setup(): 这不是生命周期钩子&#xff0c;但它是组合API的入口点&#xff0c;用于执行任何启动逻辑。 更新周期 onBeforeMount(): 在组件挂载之前调用&#xff0c;此时虚拟…

LLM大语言模型研究方向总结剖析

大语言模型&#xff08;LLM&#xff09;的研究方向主要涵盖以下几个方面&#xff1a; 1. 模型架构改进 目标&#xff1a;提高模型的性能和通用性&#xff0c;减少计算资源消耗。方法&#xff1a; 混合专家模型&#xff08;Mixture of Experts, MoE&#xff09;&#xff1a;通…