运行时库链接方式实践指南(MT、MD、MTd、MDd)

news2024/12/26 2:41:00

前言

笔者曾经编译一个库提供给使用者,提供库后发现由于运行时库连接方式不一致,导致使用者无法连接笔者提供的库。另一方面,理解和选择正确的运行时链接方式对于构建高效、可靠的应用程序至关重要。
因此,本文将展开运行时库的基本概念、讨论不同的运行时链接类型,以及如何根据项目需求选择最合适的链接方式。

什么是运行时?

运行时库(Runtime Library):这是一组标准化的软件函数集合,提供程序运行时所需的基本服务,比如I/O处理、内存管理等。例如标准模板库、C函数库等。

运行时库链接方式

运行时链接方式关主要分为两大类:静态链接和动态链接。

静态链接

静态链接是在编译时期将所有必要的库函数代码直接打包到最终的可执行文件中。静态链接产生的可执行文件通常体积较大,但它们不依赖外部的库文件,提高了应用的独立性和便于部署。

动态链接

与静态链接相对,动态链接是在运行时期加载所需的运行时库(通常是动态链接库DLL或共享对象SO)。动态链接的应用程序体积较小,可以实现库文件的共享使用,节省系统资源。

如何选择链接方式

选择链接方式时,需要综合考虑多个因素:

  • 部署简易性:如果需要简化部署过程,不希望处理外部的运行时库依赖,静态链接是一个不错的选择。

  • 体积和资源占用:如果对可执行文件的体积和内存占用有严格要求,动态链接可以减少重复的库代码占用。

  • 更新和维护:动态链接便于库文件的更新和维护,特别是当涉及到安全更新和修复时。

  • 兼容性:在有些环境中,动态链接更受欢迎,因为它保证了与系统的兼容性和一致性。

  • 特殊需求:对于需要插件或按需加载功能的应用,运行时动态链接或延迟加载等技术可能更合适。

MSVC实战

MSVC(Microsoft Visual C++)的编译选项MT、MD、MTd、MDd指定了程序是静态链接到运行时库还是动态链接,以及是否是调试版本的库。

以下是每个选项的含义:

  • MT:将程序与多线程版的静态运行时库进行链接。
  • MD:将程序与多线程版的动态运行时库(DLL)进行链接。
  • MTd:将程序与多线程版的静态运行时库进行链接,并且是调试版。
  • MDd:将程序与多线程版的动态运行时库(DLL)进行链接,并且是调试版。

MT 和 MD 分别代表:MT: Multi-Threaded和MD: Multi-Threaded DLL。早期的 Microsoft Visual C++ 版本中,存在单线程版本的运行时库,这些运行时库不支持多线程程序,从 Visual Studio 2005 开始,所有的运行时库都是多线程的(MT 或 MD),单线程的运行时库已经被淘汰。

优缺点

  • MT/MTd(静态链接)的优点是不需要在部署时包含额外的运行时库DLL文件,因为所有的运行时代码都已经包含在最终的可执行文件中。这简化了部署过程并减少了对环境的依赖。缺点是最终的可执行文件会比较大(因为把运行时库二进制也带进来了),如果项目中多个库使用了静态链接运行时库,也会出现重复的、冗余的代码占用内存。
  • MD/MDd(动态链接)的优点是可执行文件体积较小,多个程序可以共享同一份运行时库的副本,节省资源。缺点是在部署程序时需要确保正确版本的运行时库DLL文件也被安装在目标系统上,否则程序无法运行。

如果使用动态链接,但是没有打包运行时库会怎样?

许多开发者都可能遇到忘记打包运行时库的场景,表现上是在自己电脑上正常运行,但是发布到其他电脑上提示找不到xxx.dll,例如:
在这里插入图片描述
网上也提供了很多接近方案,例如VC Runtime 集合,包含了各种版本的 Visual C++ 运行时库的集合。如果一个应用程序是使用特定版本的 Visual Studio 编译的,并且使用了动态链接库(DLL),那么它就需要相应版本的 VC Runtime 来确保正确运行。

VC Runtime 集合的出现主要是为了解决以下问题:

  1. 版本兼容:不同的应用程序可能需要不同版本的 VC Runtime。一个集合包含了多个版本的运行时库,可以确保大多数应用程序的兼容性。

  2. 简化安装:用户可以一次性安装多个版本的 VC Runtime,而不需要单独下载和安装每个应用程序需要的特定版本。

  3. 解决缺失:如果用户遇到因为缺少 VC Runtime 导致的问题,安装集合包可以快速解决缺失的库文件问题。

从某种角度上来说,VC Runtime 集合的存在并不直接代表软件开发者没有正确打包动态运行时库,而是因为操作系统或软件的多样性和复杂性,使得拥有一个集合包来解决潜在的兼容性问题变得更加方便和必要。不过,为了减少不必要的用户反馈,最佳实践仍然是我们在软件分发时包括所有必要的依赖,确保自己的软件不出现运行时库的缺少的问题。

其他编译器的情况

在Clang和GCC上的对应选项:它们都支持静态链接和动态链接的概念,但是Clang和GCC在选择运行时库时和MSVC的选项不一样。

  • 在GCC中,你可以使用-static选项来静态链接到库。GCC默认动态链接到glibc。
  • 在Clang中,链接方式的选择也可以通过指定链接器(linker)参数来实现,比如使用-static进行静态链接。

在Linux上,通常默认链接到系统的动态运行时库,因此不需要特别指定。如果需要静态链接,可能需要确保静态版本的运行时库已经安装,并在链接时指定对应的选项。

在使用静态链接时,需要确保遵守所有依赖库的许可协议,因为静态链接可能会将代码合并到可执行文件中。

在编译大型项目中的实践

大型项目,例如QtFramework,在配置时一般都有编译选项支持选择如何链接运行时库,以满足开发者自定义编译的需求。
翻阅Qt源码,可以找到这个选项:
在这里插入图片描述
通过config help也能找到:
在这里插入图片描述
QT默认的编译选项是-MD,当这个选项开启时,会将-MD替换为-MT。
在这里插入图片描述

其他的开源项目也是类似,基本都会有参数可以让开发者自定义选择运行库链接方式,因为如果在库中使用库,那么链接方式必须一样才能被正确链接。

为什么在同一个项目中,库的运行时库的链接方式必须一样

在同一个项目中,所有组件使用相同的运行时库链接方式是非常重要的,主要原因是确保一致性、稳定性和避免潜在的冲突。具体来说:

1. 对象内存管理

不同的运行时库可能有不同的内存管理机制。如果一个对象在一个运行时库中被创建(分配内存),而在另一个运行时库中被销毁(释放内存),可能会导致内存泄漏或者更糟糕的情况。确保所有库使用相同的运行时库可以防止这种情况发生。

2. 全局状态的一致性

静态链接的运行时库将其全局状态编译进每个可执行文件或库中。如果一个项目中混用了静态和动态链接的运行时库,可能导致有多个独立的全局状态实例存在于同一个进程中,这会导致异常行为,比如不一致的全局变量状态、初始化和终止序列混乱等。

3. C++异常处理

在C++中,如果不同的组件使用了不同的运行时库,可能会导致异常处理不兼容。例如,一个用MDd编译的DLL抛出的异常可能无法被用MTd编译的可执行文件正确捕获或处理。

4. 类型定义和实现

运行时库通常包含了标准类型和函数的实现。如果不同的运行时库版本被混合使用,可能会导致类型定义上的冲突或者不同的实现之间的不兼容,导致运行时错误。

5. 线程和同步对象

多线程编程通常依赖于运行时库提供的同步机制,如互斥锁和条件变量。如果混用不同的运行时库,线程同步对象的行为可能会不一致,导致死锁或竞争条件。

6. 依赖和链接问题

如果项目中的不同部分链接了不同的运行时库,可能会出现难以诊断的链接错误,因为链接器可能无法解析多个版本的符号和库。

为了确保软件稳定运行,维护性和可预测性,需要在同一个项目中使用相同的运行时库链接方式。如果必须混用不同的链接方式,往往会有编译器链接报错。

结语

在软件开发中,了解不同运行时的特点并实际应用它们,或者编译出正确的库提供给使用方,是每个软件工程师技能库中不可或缺的一部分。
通过本文系统性的介绍,相信你对运行时库的概念、特点。一致性的重要性有了更深的认识。
如果想要了解如何确定在软件分发时(安装包)需要打包哪些运行时库文件,请参考:《深入解析VC Runtime:什么是vcruntimeXXX.dll和api-ms-win-crt-runtime-X-X-X.dll?》

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

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

相关文章

web前端课程设计——农产品购物车

该课程设计使用的环境为:HTMLcssJavaScript,vue3,creat-vue脚手架工具,vscode编辑器 其中实现的功能为:购物车管理,商品展示。 1.购物车管理中包含对商品数量进行加减,对商品进行全选或反选操作,删除单个商品或批量删除商品。 …

C++ | Leetcode C++题解之第189题轮转数组

题目&#xff1a; 题解&#xff1a; class Solution { public:void reverse(vector<int>& nums, int start, int end) {while (start < end) {swap(nums[start], nums[end]);start 1;end - 1;}}void rotate(vector<int>& nums, int k) {k % nums.size…

Android AOSP 编译并烧录到Google Pixel4XL

简介 AOSP&#xff08;Android Open Source Project&#xff09;是Android系统的开源版本&#xff0c;任何人都可以下载、编译和修改。手头上有一台Pixel 4XL&#xff0c;尝试编译AOSP并将其烧录到的设备上。 准备工作 在开始之前&#xff0c;您需要确保您的电脑满足以下条件…

文旅景区科技馆增加5D影院项目VR游乐场

王屋山风景名胜区增加20座5D影院设备&#xff0c;5D影院不像普通电影院&#xff0c;5D影院座椅可以根据影片播放内容&#xff0c;进行实时摆动和各种特效&#xff0c;闪电&#xff0c;振臀振臂&#xff0c;泡泡等个种特效。影片内容可以进行定制&#xff0c;根据景区文化风光&a…

OnlyOffice-8.1版本深度测评

2024年6月19日&#xff0c;ONLYOFFICE 发布了最新版本 8.1&#xff0c;带来了超过30项新功能和432个 bug 修复。本文将详细评测该版本的新功能和改进&#xff0c;帮助用户全面了解这一升级带来的实际体验提升。 一、功能全面的 PDF 编辑器 PDF 是日常工作中不可或缺的文件格式…

Waiting for table flush故障处理

故障排查 1 找到正处于open状态的表 show open tables where in_use >1; 2 找到引发故障的慢查询 ① 找到阻塞flush tables的慢查询 SELECT * FROM information_schema.PROCESSLIST WHERE info IS NOT NULL AND state NOT LIKE ‘Waiting for table flush’ AND info …

CentOS7.6安装RabbitMQ

前言&#xff1a;因为RabbitMQ是ERlang语言编写所以要先安装ERlang再安装RabbitMQ 安装ERlang 借鉴前辈原文地址&#xff1a;https://www.cnblogs.com/fengyumeng/p/11133924.html 第一步&#xff1a;安装依赖 yum -y install gcc glibc-devel make ncurses-devel open…

Linux-CentOs7 基础配置

目录 一、安装ifconfig二、配置静态IP 一、安装ifconfig 查找ifconfig存在哪个包下 yum search ifconfig下载对应的资源包 yum install net-tools.x86_64检查是否安装成功 ifconfig二、配置静态IP 点击编辑 — 虚拟网络编辑器&#xff0c;选择VMnet8&#xff0c;点击NET设置&am…

【C++题解】1711. 输出满足条件的整数1

问题&#xff1a;1711. 输出满足条件的整数1 类型&#xff1a;简单循环 题目描述&#xff1a; 有这样的两位数&#xff0c;其十位上的数字比个位上的数字要大&#xff0c;且十位和个位上的数字之和为偶数&#xff0c;请找出所有的满足条件的 2 位数。 输入&#xff1a; 无。…

Hive基础知识(十九):Hive 自定义函数

1. 自定义函数 1&#xff09;Hive 自带了一些函数&#xff0c;比如&#xff1a;max/min 等&#xff0c;但是数量有限&#xff0c;自己可以通过自定义 UDF 来方便的扩展。 2&#xff09;当 Hive 提供的内置函数无法满足你的业务处理需要时&#xff0c;此时就可以考虑使用用户自…

山寨币大额解锁抛压拖累比特币:10X Research 深度剖析市场动荡

加密货币市场大幅下跌&#xff0c;山寨币损失惨重 在经历了几个月的强劲表现后&#xff0c;加密货币市场最近经历了一轮大幅下跌&#xff0c;特别是山寨币损失惨重。10X Research 最近在其Newsletter中发表了观点&#xff0c;认为山寨币大额解锁所带来的抛压正在拖累比特币。本…

win11安装VMware虚拟机,启动系统后蓝屏,安装虚拟机卡在虚拟网卡界面的解决办法

机缘和遇到的问题 由于最近618换了台新笔记本电脑&#xff0c;然后系统自带的操作系统是windows 11 家庭版本&#xff0c;由于工作需要用到window10的环境&#xff0c;不得不安装一个虚拟机来解决问题&#xff0c;然后就把这次安装VMware虚拟机遇到的坑给大家分享一下&#xf…

AI视频模型Sora核心功能以及应用场景

随着人工智能技术的飞速发展&#xff0c;AI在视频处理和生成领域的应用正变得越来越广泛。Sora&#xff0c;作为新一代AI视频模型&#xff0c;展示了前所未有的潜力和创新能力。本文将深入探讨Sora的功能、应用场景以及它所带来的革命性变化。 一、Sora的核心功能 1.1 视频生…

cpu scheduling cpu调度

soft real-time Vs hard real-time scheduling Real-Time CPU Scheduling Can present obvious challengesSoft real-time systems – Critical real-time tasks have the highest priority, but no guarantee as to when tasks will be scheduledHard real-time systems – …

ONLYOFFICE 桌面编辑器 8.1 发布:全新 PDF 编辑器、幻灯片版式、增强 RTL 支持及更多本地化选项

目录 什么是ONLYOFFICE&#xff1f; ONLYOFFICE 主要特点包括&#xff1a; 官网信息&#xff1a; 1. 功能齐全的 PDF 编辑器 1.1 编辑 PDF 文本 1.2 插入和修改对象 1.3 创建和填写表单 2. 幻灯片版式功能 2.1 快速应用幻灯片版式 2.2 动画窗格的改进 3. 文档编辑、…

交通 | 机器学习 + 大规模TSP/VRP求解

封面图来源&#xff1a;https://xkcd.com/399/ 推文作者&#xff1a;丁建辉&#xff0c;陈泰劼&#xff0c;张云天 本文针对旅行商问题&#xff08;Travelling salesman problem, TSP&#xff09;和车辆路径规划问题&#xff08;Vehicle routing problem, VRP&#xff09;这一类…

数据库精选题(五)(事务、并行控制与恢复系统)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;数据库 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 前言 概论 事务 并发控制 恢复系统 三…

Python | Leetcode Python题解之第190题颠倒二进制位

题目&#xff1a; 题解&#xff1a; class Solution:# param n, an integer# return an integerdef reverseBits(self, n):n (n >> 16) | (n << 16);n ((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8);n ((n & 0xf0f0f0f0) >&g…

198.回溯算法:子集(力扣)

代码解决 class Solution { public:// 用于存储当前子集的临时向量vector<int> res;// 用于存储所有子集的结果向量vector<vector<int>> result;// 回溯函数void backtracing(vector<int>& nums, int index) {// 每次递归调用都将当前子集添加到结…

CBSD创建和管理bhyve容器Ubuntu@FreeBSD

首先&#xff0c;创建bhyve cbsd bconstruct-tui 然后启动 cbsd bstart bub22 启动后提示 init_systap: waiting for link: igb0 Looks like /usr/jails/vm/bub22/dsk1.vhd is empty. May be you want to boot from CD? [yes(1) or no(0)] yes确认 然后使用cbsd blogi…