理解和创建Windows和Linux下的动态和静态库区别

这篇具有很好参考价值的文章主要介绍了理解和创建Windows和Linux下的动态和静态库区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、引言

在计算机编程的世界中,库是一个非常重要的改变。它的出现提供了一种共享和重用代码的可能性,复杂的程序因为动态库的出现而变得简洁和方便。然而,库并不是单一的:它们可以是动态的,也可以是静态的,每一种类型都有其使用场景。在本文中,我们将深入探讨动态库和静态库的概念,每种类型都有其优点和使用场景。讨论的范围将会集中两种最为常见的平台——Windows和Linux,主要内容还是帮助读者创建一个在自己平台下使用的动态库。

二、静态库和动态库基础知识

在顺利创建并使用动态库之前,让我们先来了解一下关于这两个库的概念。

2.1 动态库

动态库在程序实际运行时才会被加载到内存,多个程序可以共用这个动态库;Windows动态库以.dll结尾,而在Linux下则以.so结尾,其优点在于:

  • 节省内存。多个程序如果使用到了同一个动态库,仅需加载一次内存,从而达到节省内存的作用;
  • 模块化设计。动态库是一个模块化设计,每个库专注其特定的功能,增加了代码的可读性和维护性;
  • 简化更新和修复过程:因为是运行时才加载,如果符号保持不变,更新功能只需要替换掉原来的动态库即可;
  • 剥离常用函数,使得维护变得容易。这一个和模块化不同,模块化的功能单一,而剥离这个功能,主要是为了维护不同功能;
  • 跨语言兼容。不同语言也可以通过动态库使用对应的功能,使得其变得与语言无关;
  • 降低磁盘空间。同一个功能只需要存储一份动态库,而不需要每个程序都带有相应的代码段;

2.2 静态库

静态库在程序进行编译之时就被链接到程序中,每个程序都独占这部分功能代码。Windows中以.lib结尾,而Linux则以 .a结尾。一般而言[1],静态库含有对应功能的所有实现,其优点在于:

  • 独立性。静态库被链接到应用程序,将内容直接“注入”应用程序,不再需要存放着内容的动态库.dll,程序的部署和分发变得简单,无需担心目标系统是否具有对应的动态库;
  • 兼容性。版本冲突基本上不会出现,因为每个程序在编译之时就已经完成了版本冲突检查,如果有兼容性问题,编译器就被暴露出来了;
  • 性能。使用静态库的应用程序无需在运行时进行加载,降低了程序开销;
  • 安全性。静态库在编译时已经确定,攻击者更加难以通过替换库中的函数进恶意程序注入;(这就是为什么破解替换动态库就可以完成,大概率是因为替换掉了验证部分函数)

下面是一张比较动态库和静态库优缺点的表格:

动态库 静态库
优点 1. 节省内存 2. 支持模块化设计 3. 代码重用 4. 简化更新和修复过程 5. 跨语言兼容性 6. 减少磁盘空间的使用 1. 独立性 2. 兼容性 3. 性能 4. 安全性
缺点 1. 可能导致版本冲突 2. 运行时需要加载和链接库,可能影响性能 1. 如果库代码更新,所有使用此库的程序都需要重新编译和链接 2. 程序文件大小通常比动态链接的程序更大

三、Windows下动态库和静态库的创建

3.1 如何创建一个动态库?(VS2022为例)

理解和创建Windows和Linux下的动态和静态库区别
新建一个项目,选择Dynamic-Link Library(DLL),VS自动帮我们写了工程配置和部分用于优化的代码。对应源代码和头文件:

#include "pch.h" 
#include "addition.h"
int AddNumbers(int a, int b)
{
    return a + b;
}
#ifndef ADDITION_H
#define ADDITION_H

__declspec(dllexport) int AddNumbers(int a, int b);

#endif

在Windows平台上,默认情况下,函数和变量不会被自动导出为动态链接库(DLL)的一部分。如果你想要将函数或变量导出为DLL可见的导出项,需要显式地使用
__declspec(dllexport) 关键字进行标记。

在界面上选择目标库的架构和构建模式(Debug或者Release)。如下:
理解和创建Windows和Linux下的动态和静态库区别
这里我选择了x64 Debug进行库的生成。在对应目录下可以找到如下内容:理解和创建Windows和Linux下的动态和静态库区别
一共生成了四个文件分别是,dll exp lib pdb

  • dll (Dynamic Link Library)动态链接库:包含已编译的代码和数据,程序运行时将会动态加载;
  • exp(Exported File)导出文件。是关于dll的导出文件,描述导出函数和数据的名称和属性,含有导出数据和函数的符号信息,其他程序可以根据此文件进行符号解析和导入;
  • lib(Library):以lib结尾的文件按功能可以分为两部分,分别是导出库和一般意义上的静态链接库,不过Windows大多数情况都是以导出库形式导出所需要的动态库和函数
  • PDB(Program Database) PDB文件时调试符号文件,包含编译器生成的符号信息,用于映射源代码和二进制代码之间的关系,调试器能根据此文件,正确解析符号并提供详细的调试信息,比如函数名、行号等;

动态库导出将代码声明为导出,使用者将库中的函数标记为导入,以便使用其功能。

再次强调一下,在windows生成动态库过程中的lib和linux下a不一样,虽然他们都叫做静态库,前者是导出库,后者是含有具体代码的源文件二进制代码。

2.2 如何创建静态库?(以VS2022为例)

步骤和动态库基本相同:
理解和创建Windows和Linux下的动态和静态库区别
理解和创建Windows和Linux下的动态和静态库区别

  • idb(Intermediate Debug)中间调试文件,主要是为了加快重复生成静态库速度而出现的;
  • pdb 同动态库
  • lib 静态库,我们需要的

四、Linux下创建动态和静态库

4.1 如何创建一个静态库?(Linux下的CMake为例)

CMakeLists.txt:

cmake_minimum_required(VERSION 3.15)
project(buildLib)
set(LIBRARY_OUTPUT_PATH ../lib)
add_library(myLib STATIC library.cpp)

头文件:

//library.h
#ifndef ___LIBRARY_H
#define ___LIBRARY_H
void hello();
int myadd(int,int);
#endif 

源文件:

//library.cpp
#include <iostream>
#include "library.h"
void hello() {
    std::cout << "Hello, World!" << std::endl;
}
int myadd(int i,int j)
{
    return i+j;
}

相对简单一些,CMakeLists.txt同级目录下,可以看到生成的静态库libmyLib.a
理解和创建Windows和Linux下的动态和静态库区别

4.2 如何创建一个动态库(Linux下的CMake为例)

Linux和Windows对于生成库的默认行为不同,前者在默认情况下是全部导出的,后者则是需要显式说明导出的符号。全部导出的好处是,可以减少繁琐的导出或者导入函数,缺点是体积变差。关键字 __declspec用于标识一个符号是否需要输出,如果在Windows下你需要全部输出,则设置变量CMAKE_WINDOWS_EXPORT_ALL_SYMBOLSON。下面是一个头文件示例(充分考虑了跨平台特性):

// library.h
#ifndef LIBRARY_H
#define LIBRARY_H

// Check if we are on Windows
#ifdef _WIN32
    #define LIBRARY_API __declspec(dllexport)
    #define LIBRARY_LOCAL
// Check if we are on Unix (Linux, MacOS, etc.)
#elif __GNUC__ >= 4
    #define LIBRARY_API __attribute__ ((visibility ("default")))
    #define LIBRARY_LOCAL  __attribute__ ((visibility ("hidden")))
#else
    #define LIBRARY_API
    #define LIBRARY_LOCAL
#endif

#ifdef BUILD_DLL
    LIBRARY_API void hello();
    LIBRARY_API int myadd(int,int);
#else
    void hello();
    int myadd(int,int);
#endif

#endif // LIBRARY_H

这个头文件做了一些宏处理,使用库和编译库都可以使用同一个头文件。

源文件:

//library.cpp
#include <iostream>
#include "library.h"
void hello() {
    std::cout << "Hello, World!" << std::endl;
}

int myadd(int i,int j)
{
    return i+j;
}

CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.15)
project(buildLib)
set(LIBRARY_OUTPUT_PATH ../lib)
add_library(myLib SHARED library.cpp)

请注意,如果你在Windows下使用这个CMakeLists.txt,如果你不手动添加一些导出关键字,生成动态库下不会出现Windows平台所需要的lib文件,除非你手动指定了导出的符号。

生成的文件如下:
理解和创建Windows和Linux下的动态和静态库区别

五、小结

动态和静态库都是编程上常见的技术,它们各自有各自的特点。在Windows和Linux下他们都有相应的概念,对于Windows而言,为了简化动态库.dll的使用,Windows提出了一种.lib文件单独解决和揭示应用程序中使用符号的问题,而Linux则将这部分工作放入了.so中。需要特别注意的是Windows在使用动态库要使用到的.lib不一定与Linux.a一样,它有可能是为了解决动态库使用问题的。这就是为什么我们在Windows平台使用库的使用需要用到两个文件,一个是.dll 另一个则是lib;在Linux下,只需要在.a.so选择一个即可进行编译。为了保证动态库的使用效率,Windows默认情况下将动态库的所有符号都进行了隐藏,也就是默认不输出;而Linux则是将所有符号进行了输出,所幸的是,它们都有相应的关键字进行可见性的控制。之前遇到Windows生成不了.lib从而导致没有办法使用其中的库,其实就是因为没有相应标记输出的符号,如果没有输出符号,Windows当然也不会为你生成对应的代码。


[1] 在Windows中,.lib文件除了可以用作静态链接库外,还有另一种用途,就是用作动态链接库(.dll)的“导出库”。文章来源地址https://www.toymoban.com/news/detail-479807.html

到了这里,关于理解和创建Windows和Linux下的动态和静态库区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux系统编程】Linux下的编译器——gcc/g++的使用 及 动态库和静态库的认识

    这篇文章我们继续学习Linux中的开发工具,今天要学的是: Linux下的编译器——gcc/g++ 我们先来简单了解一下它们的概念: gcc (GNU Compiler Collection) 和 g++ 是 Linux 系统上最常用的编译器。它们是 GNU 组织开发的一套开源编译器工具集。 gcc: gcc 是 GNU 编译器集合中的 C 语言编译器。

    2024年02月16日
    浏览(31)
  • 详解Linux下静态库/动态库的生成和使用(含代码示例和操作流程)&&动态库和静态库的区别

    关于gcc的使用方法可以参考下方链接博客: Linux下详解gcc编译过程(含代码示例) gcc使用教程 库是一种组件技术。 库里封装了数据和函数,提供给用户程序调用。 库只执行到第三阶段编译,没有链接。 库的使用可以使程序模块化,提高程序的编译速度,实现代码复用。

    2024年02月15日
    浏览(27)
  • Linux操作命令&静态库和动态库区别&大小端&孤儿僵尸进程

    cd:切换当前目录 ls:查看当前文件与目录 grep:通常与管道符命令一起使用,用于对一些命令的输出进行筛选和加工 cp:复制文件或文件夹 mv:移动文件或文件夹 rm:删除文件或文件夹 ps:查看进程情况 kill:向进程发送信号 tar:对文件进行打包 cat:查看文件内容 top:查看

    2024年02月16日
    浏览(27)
  • 【看表情包学Linux】软硬链接 | 软连接数 | 创建软硬链接 | 动静态库 | 生成静态库 | 生成动态库

       🤣  爆笑 教程  👉 《看表情包学Linux》👈   猛戳订阅     🔥 💭 写在前面: 上一章我们讲解了 inode,为文件系统收了尾,这几章我们充分地讲解完了文件系统的知识点,现在我们开始开始学习软硬链接了。如果没有文件系统的铺垫,想直接理解软硬链接难免有些困

    2024年02月14日
    浏览(29)
  • Ubuntu (Linux) 下创建软链接(即符号链接,相当于windows下的快捷方式)方法

    使用创建软链接的命令 Reference(注) :

    2024年01月24日
    浏览(44)
  • 静态网页和动态网页区别

    1) 更新和维护 静态网页内容一经发布到网站服务器上,无论是否有用户访问,这些网页内容都是保存在网站服务器上的。如果要修改网页的内容,就必须修改其源文件,然后重新上传到服务器上。静态网页没有数据库的支持,当网站信息量很大的时候网页的制作和维护都很困

    2024年02月13日
    浏览(32)
  • 静态路由和动态路由的区别

    在网络环境中,数据包从源主机传送到目标主机需要经过一系列路由器,这个过程被称为路由。路由有两种基本类型:静态路由和动态路由。本文将深入探讨这两种路由方式的定义、特点、工作原理,以及使用场景,并进行详细的对比分析。 1.1 定义与特点 静态路由是网络管

    2024年02月05日
    浏览(24)
  • 如何理解mybatis中sql的动态和静态

    在MyBatis中,SQL的语句可以分为动态和静态。静态SQL是指在应用程序编写SQL语句时已经固定好的SQL语句,而动态SQL则是可以根据条件动态地生成SQL语句。 动态SQL在实际开发中非常常见,它可以根据条件进行if、choose、when、otherwise、foreach等元素的组合拼接,从而生成不同的SQL语

    2024年02月13日
    浏览(24)
  • 动态ip与静态ip的区别是什么?

    动态ip和静态ip的区别在于: 动态ip可以自动获取IP地址,静态ip需要手动设置IP地址。 动态ip一般用于局域网内部或小型企业网中,静态ip一般用于大型企业网或骨干网等对安全性要求高的场合。 在网速上,动态ip和静态ip没有区别。 动态ip不是一个真实的IP地址,静态ip是可以

    2024年02月06日
    浏览(32)
  • 静态链接库和动态链接库的区别

    在编译时将库的代码( .lib文件 )和应用程序的代码合并在一起,生成一个单独的可执行文件。 发布时非常方便,直接一个.exe文件即可 库的代码在编译时和链接时与应用程序分开。应用程序包含对库的引用( .lib文件 ,在这里被称为导入库),但不包含库的实际代码。 在 运行

    2024年02月11日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包