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

news2024/11/17 3:30:09

一、引言

在计算机编程的世界中,库是一个非常重要的改变。它的出现提供了一种共享和重用代码的可能性,复杂的程序因为动态库的出现而变得简洁和方便。然而,库并不是单一的:它们可以是动态的,也可以是静态的,每一种类型都有其使用场景。在本文中,我们将深入探讨动态库和静态库的概念,每种类型都有其优点和使用场景。讨论的范围将会集中两种最为常见的平台——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为例)

在这里插入图片描述
新建一个项目,选择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)。如下:
在这里插入图片描述
这里我选择了x64 Debug进行库的生成。在对应目录下可以找到如下内容:在这里插入图片描述
一共生成了四个文件分别是,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为例)

步骤和动态库基本相同:
在这里插入图片描述
在这里插入图片描述

  • 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
在这里插入图片描述

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


[1]为什么我说是一般情况?在Windows中,.lib文件除了可以用作静态链接库外,还有另一种用途,就是用作动态链接库(.dll)的“导入库”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/634581.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

达梦数据库的下载与安装(Linux)

一、创建用户组 1、创建一个用户组和用户 添加分组 groupadd dinstall添加用户 useradd -g dinstall dmdba设置用户名和密码 echo "dameng123" | passwd --stdin dmdba查看操作系统中id为 dmdba 的用户的用户ID&#xff08;uid&#xff09;、组ID&#xff08;gi…

web漏洞-逻辑越权之水平垂直越权全解(33)

他是业务逻辑层面&#xff0c;和一些业务方便应用的安全问题&#xff0c;这个是因为代码层面没用考虑到的逻辑关系所造成的安全问题&#xff0c;越权是其中一个比较关键的问题。登录是指在登录这里出现了安全问题&#xff0c;业务等等今天只说越权。 越权漏洞 分为水平和垂直…

容器镜像按层分析工具dive

概述 dive是一个容器镜像分析工具&#xff0c;可以直观的看到容器每一层变动了哪些文件&#xff0c;每一层占用的磁盘空间&#xff0c;这样也就可以看到镜像的历史构建过程&#xff1b;同时也可以看到镜像的磁盘空间使用率&#xff0c;面对特别大的镜像文件是&#xff0c;可以…

【论文随笔】Rewrite-Based Decomposition of Signal Temporal Logic Specifications

文章目录 Overview1 IntroLTL任务分解STL任务分解本文工作 Background and Problem DefinitionSTLAgent假设与问题方法 An STL Rewriting SystemRewriting SystemFormula Rewrite DAG Decomposing STL智能体编队任务分解最优分解 Exploring the Formula Rewrite DAG心得体会 多…

如何创建可引导的 macOS 安装介质

如何创建可引导的 macOS 安装介质 如何创建可引导的 macOS 安装器 | 如何制作 macOS USB 启动盘 请访问原文链接&#xff1a;https://sysin.org/blog/macos-createinstallmedia/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.or…

asp.net卷烟物价管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net卷烟物价管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 asp.net卷烟物价管理系统VS开发sq…

清华青年AI自强作业hw3_2:前向传播和反向传播实战

清华青年AI自强作业hw3_2&#xff1a;前向传播和反向传播实战 实现过程各层参数维度分析拟合结果相关链接 一起学AI系列博客&#xff1a;目录索引 前向传播和反向传播的公式理解化用于作业hw3_2中&#xff1a;&#xff1a;用NN网络拟合小姐姐喜好分类 完成前向传播、反向传播算…

【JavaEE进阶之Spring】一分钟让你学会什么是Spring以及如何使用创建Spring

前言&#xff1a; &#x1f49e;&#x1f49e;今天我们正式进入到JavaEE进阶的学习中了&#xff0c;在JavaEE进阶的学习中&#xff0c;我们最主要的就是学习Spring框架。 &#x1f49f;&#x1f49f;那我们从今天就要逐渐从最基础的Spring开始&#xff0c;教会大家什么是Spring…

54、基于51单片机饮水机温度水位控制无线蓝牙APP控制报警系统设计(程序+原理图+PCB源文件+Proteus仿真+参考论文+开题报告+元器件清单等)

方案的选择 方案一&#xff1a;采用51单片机作为控制核心&#xff0c;配合无线蓝牙模块、水温加热模块继电器开关、基于Dallas单线数字式的DS18B20温度传感器模块、蜂鸣器报警模块、按键模块、LCD1602液晶显示器模块、晶振电路模块、复位电路模块以及电源模块为一体构成无线水…

winsw使用——将Nginx和Jar包注册到WIN服务

文章目录 1.winsw介绍2.注册Nginx到win服务2.1 首先将下载的winsw下并改名2.2 nginx-service.exe.config配置2.3 nginx-service.xml配置2.4 nginx-service安装到服务 3.注册Jar包到win服务3.1 复制winsw文件并改名3.2 创建xml配置文件3.3 执行安装命令 1.winsw介绍 Windows Se…

ChatGPT Prompt Engineering for Developers from DeepLearning.AI

链接&#xff1a;https://learn.deeplearning.ai/chatgpt-prompt-eng/lesson/1/introduction In this course, there are some example codes that you can already run in Jupyter Notebook. Below, I will write down the core knowledge points (how to build a prompt and…

CSS基础学习--4 创建式样

一、插入样式表的几种方法&#xff1f; 外部样式表内部样式表内联样式 二、外部样式表 使用前提&#xff1a;当样式需要应用于很多页面时&#xff0c;外部样式表将是理想的选择。 在使用外部样式表的情况下&#xff0c;你可以通过改变一个文件来改变整个站点的外观。每个页…

Ognl使用总结

目录 一、简介二、快速入门三、详细使用3.0 Ognl操作3.1 基本数据类型3.2 对象类型3.3 List集合3.4 Set集合3.5 Map集合3.6 数组3.7 静态调用3.8 算术运算3.9 逻辑运算3.10 同时执行多个表达式3.11 位运算 一、简介 OGNL&#xff08;Object-Graph Navigation Language的简称&a…

开始使用chat-gpt4

目录 一、说明 二、安装步骤 三、测试效果咋样 &#xff08;1&#xff09;写代码能力 &#xff08;2&#xff09;回答问题能力 &#xff08;3&#xff09;写作能力 一、说明 参考&#xff08;非常感谢这位博主的分享&#xff09;&#xff1a;http://t.csdn.cn/qypw9 注意&…

FTP服务器项目

文章目录 1. 项目简介2. FTP协议和用到指令说明2.1 FTP协议详解2.2 指令说明 3. FTP项目的类图分析3.1 UML3.2 工厂类XFtpFactoryXFtpFactory.hXFtpFactory.cpp 2.2 XFtpTaskXFtpTask.hXFtpTask.cpp 2.3 XFtpServerCMDXFtpServerCMD.hXFtpServerCMD.cpp 4. 运行演示FileZilla的…

数字逻辑期末必刷卷(基础卷)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 &#x1f4a1;一、填空题&#xff08;每空1分&#xff0c;共20分&#xff09;&#x1f4a1;二、单项选择题&#xff08;每小题2分&#xff0c;共20分&#xff09;&a…

第七章 Linux实际操作——组管理和权限管理

第七章 Linux实际操作——组管理和权限管理 7.1 Linux组基本介绍7.2 文件、目录 所有者7.2.1 查看文件的所有者7.2.2 修改文件所有者 7.3 组的创建7.3.1 基本指令7.3.2 应用实例 7.4 文件、目录所在组7.4.1 查看文件、目录所在组7.4.2 修改文件、目录所在组 7.5 其他组7.6 权限…

观澜南林輋旧改回迁房--周边巨量旧改,未来区政府核心商圈。

项目亮点 观澜福城街道办旧改最集中的区域&#xff0c;且地铁4号的茜坑站就在门口&#xff01;未来一区域成为龙华区政府的中心地段。本项目拆迁约10万&#xff0c;主打高端商业综合体&#xff0c;项目规划27班九年一贯性学校&#xff0c;约4万多平用于建设公共设施、绿地。 …

ROS学习——通信机制(服务通信)

2.2.3 服务通信自定义srv调用A(C) Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 068服务通信(C)3_客户端优化_Chapter2-ROS通信机制_哔哩哔哩_bilibili 一、理论模型 服务通信也是ROS中一种极其常用的通信模式&#xff0c;服务通信是基于请求响应模式的&#xf…

【Java|多线程与高并发】volatile关键字和内存可见性问题

文章目录 1.前言2. 编译器优化带来的内存可见性问题3. 使用volatile保证内存可见性5.volatile不能保证原子性以JMM的角度看待volatile总结 1.前言 synchronized和volatile都是Java多线程中很重要的关键字&#xff0c;但它们的作用和使用场景有所不同。 synchronized关键字可以…