首页 > 编程语言 >【一分钟学C++】动态库与静态库

【一分钟学C++】动态库与静态库

时间:2024-11-19 20:16:02浏览次数:3  
标签:符号 静态 导出 一分钟 C++ 库中 动态 加载

在这里插入图片描述

竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~
公众号: C++学习与探索  |  个人主页: rainInSunny  |  个人专栏: Learn OpenGL In Qt

文章目录

动态库

常见格式

  动态库是一种常见的库文件形式,主要包含以下几种格式:

  • windows:.dll
  • linux:.so
  • mac:.dylib/.framework

特点

  动态库有以下特点:

  • 运行时加载:
    动态库在程序运行时被加载到内存中,这意味着可执行文件本身不包含动态库的代码,只是符号表中引用了动态库中的接口。但是这也带来了运行环境的问题,如果当前可执行程序运行动态库环境缺失或者版本不匹配,都会导致程序运行异常。
  • 共享性:
    多个应用程序可以同时使用同一个动态库,从而节省了磁盘空间和内存。这种共享性使得动态库成为一种高效的资源利用方式。
  • 易于更新和维护
    由于动态库的代码没有被直接编译到可执行文件中,因此可以独立于应用程序进行更新,这大大简化了库的维护和版本控制。在动态库中的修改满足二进制兼容的情况下,只需要重新编译更新动态库部分,其它部分无需改动就可以完成更新。
  • 版本灵活性:
    系统可以同时存在多个版本的动态库,这为开发者提供了更大的灵活性,开发者可以手动通过 dlopen 等方式显示加载需要版本的动态库。
  • 可能影响程序启动性能:
    由于动态库需要在运行时加载,这可能会增加程序的启动时间。

加载方式

在这里插入图片描述
  当我们在 CMakLists 中添加图中所示的指令后,就实现了对 qecomponents 目标链接 Qt5::Widgets 等动态库。使用这种链接方式,当 qecomponents 被加载到内存中时,其链接的动态库也都会被加载到内存中。这样的好处是这些动态库中导出的符号对外都可以正常使用了,但是如果依赖过于复杂,会导致应用程序启动过程需要加载过多的动态库,可能有些插件类型的动态库在整个应用程序的生命周期内都不会被使用,这样就很浪费资源,同时也会让启动速度变慢。
在这里插入图片描述
  上图展示了 unix 环境 dlopen 函数的说明,该函数提供了一种手动显示加载动态库的方式。这样带来的好处是可以按需加载动态库,插件类的动态库可以在被使用的时候进行加载,避免资源浪费。

静态库

常见格式

  静态库主要包含以下几种格式:

  • windows:.lib
  • linux:.a
  • mac:.a

特点

  静态库有以下特点:

  • 运行时无关性:
    由于静态库在编译时已经被完全拷贝到链接到它的可执行程序或者动态中,因此程序在运行时与静态库再无瓜葛。这使得程序的移植变得方便,因为不需要担心运行时环境中是否存在所需的库文件。
  • 无加载耗时:
    因为静态库本身被包含在可执行程序中,程序运行时不需要单独加载,不会产生额外耗时。
  • 增大程序体积:
    如果存在多个库链接同一个静态库,可能导致静态库中的符号被重复包含,造成程序体积增大。

动态库和静态库中的符号导出

  作为一个库文件,一般都会提供一些导出符号供外部使用。图中给出了 Q_DECL_EXPORT 和 Q_DECL_IMPORT 在 windows 和 linux 上的实现,通过添加这样的前缀,可以在动态库和静态库中实现函数符号的导出。
在这里插入图片描述
  在 windows 上默认是不会导出函数符号的,一般需要手动添加导出前缀,在 linux 上,一些编译器默认开启了函数符号导出,如果需要关闭默认的函数符号导出,可以设置 -fvisibility=hidden 编译选项来实现。

常见问题

  • 静态库中的所有符号都会被链接的可执行文件或动态库包含吗?
    答:不会,就 C++11 标准来说,最小的编译单元是一个独立的 cpp 文件,如果使用到其中的符号,那么这个 cpp 中其它符号也会被包含,没有任何被使用函数的 cpp 文件中的函数符号不会被包含。另外如果需要包含静态库中所有的函数符号,可以添加下面的链接选项。
    在这里插入图片描述

  • 有办法避免静态库中的符号被重复包含吗?
    答:可以通过一个指定动态库来导出静态库中需要导出的符号,首先在静态库中需要导出符号前添加导出前缀,在指定动态库中引用这些符号,并且指定动态库链接静态库,这样其它库可以通过链接指定动态库来实现对静态库中导出符号的访问,由于都通过指定动态库链接,所以不存在重复符号包含。但是要注意的是指定动态库中需要有静态库中导出符号的引用,否者符号可能不会包含在动态库中。

  • 包含全局静态变量和局部静态变量的头文件(例如单例模式的 instance() 函数在头文件中用 static 实现),在不同动态库中引用会有问题吗?
    答:会存在隐患,例如单例期望是全局只有一份实例,但是在头文件中实现,被多个动态库中都引用了,这样会导致不同动态库中各自有一份自己的实例,可能会导致预期之外的行为。

  • 静态库编译过程中使用了其它库的函数符号但是没有链接对应库,单独编译这个静态库时会报错吗?
    答:不会,单独编译一个静态库可以认为不存在链接的过程,只是将编译出来的符号进行打包,只有编译到依赖该静态库的动态库或者可执行文件时,才会报链接错误。

关注公众号:C++学习与探索,有惊喜哦~

标签:符号,静态,导出,一分钟,C++,库中,动态,加载
From: https://blog.csdn.net/rainInSunny/article/details/143894558

相关文章

  • C++虚函数表
    一、概念在C++中,虚函数表(VirtualFunctionTable,简称vtable)是实现多态机制的一个重要底层数据结构。当一个类中包含了虚函数时,编译器会为这个类创建一个虚函数表,用来存放该类的虚函数的地址。每个包含虚函数的类的对象实例中,会隐含一个指针(通常称为虚指针,vptr),它指向所属类......
  • 什么是 C++ 中的友元函数和友元类?友元的作用是什么?有什么注意事项?
    友元函数定义友元函数是在类中声明的非成员函数,它可以访问类的私有(private)和保护(protected)成员。友元函数虽然不是类的成员函数,但它被授予了访问类内部成员的特殊权限。声明方式在类的定义中,使用friend关键字来声明友元函数。classMyClass{private:intprivateDat......
  • c++等级考试第8级第2卷
                                       道路(2024.3八级)代码#include<iostream>#include<algorithm>#include<cmath>#include<cstdio>#include<vector>#include<cstring>usingnamespacestd;st......
  • 【入门】字符串的反码c++
    #include<bits/stdc++.h>usingnamespacestd;intmain(){ //一、分析问题 //已知:一个长度不超过80个字符的字符串。 //未知:字符串的反码。 //关系:如果这是一个小写字符,则它和字符a的距离与它的反码和字符z的距离相同;如果是一个大写字符,则它和字符A的距离与它......
  • 在bug中巩固C++
    记录自己的各种报错,在错误中学习ing结构体全局变量的声明与初始化问题#include<iostream>usingnamespacestd;//声明一个结构体BooksstructBook{stringname;stringauthor;stringsubject;intid;//构造函数Book(stringname,stringa......
  • 【C++】十六进制数据的字节序排列问题、大小端
    十六进制数据的字节序排列问题,涉及到大小端(Endianness)的概念。包括它与大小端存储方式的关系。1.十六进制数据在内存中的存储定义的数据#defineFRAME_TYPE_PARAM_SET0x30010x3001是一个16位(2字节)整数。在内存中,0x3001的存储方式依赖于系统的字节序:小端......
  • C++编程:通过多线程与协程优化阻塞型任务的调度性能
    文章目录0.引言1.多线程VS多线程+协程1.1示例1:使用传统的多线程进行矩阵乘法1.2.示例2:使用协程优化阻塞型任务3.分析与对比0.引言我们知道:多线程:适用于处理计算密集型任务或IO操作较少的场景,但会因为线程切换和创建销毁的开销而影响性能。协程:适用于处......
  • 实验4 C++
    任务2:GradeCalc.cpp1#pragmaonce2#include<iostream>3#include<vector>4#include<string>5#include<algorithm>6#include<numeric>7#include<iomanip>89usingstd::vector;10usingstd::......
  • C++ 学习笔记(1):STL、Vector 与 Set
    背景最近在尝试入坑蓝桥杯,于是先从C++开始学起,这里记个笔记。这里我的笔记是跟着这个教程来的。沙比学校天天整些屁事都没什么空折腾。前言笔者是JS/TS写的比较多,以前写过C但是有点忘了,所以文章里都是和JS进行对比着方便快速理解。同时其实我还有几个小问题,嘻嘻。没......
  • C++中的友元函数和友元类&友元的作用及注意事项
    1.C++中的友元函数和友元类友元函数:友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数。类授予它的友元特别的访问权。通常,同一个开发者会出于技术和非技术的原因控制类的友元和成员函数,否则在更新类时,还需要征得其他部分的拥有者的同意。友元函数在定义上和调用......