当前位置: 首页 > news >正文

VS开发 - 静态编译和动态编译的基础实践与混用

目录

1. 基础概念

2. 直观感受一下静态编译和动态编译的体积与依赖项目

3. VS运行时库包含哪些主要文件(从VS2015起)

4. 动态库和静态库混用的情况

5. 感谢清单


1. 基础概念

所谓的运行时库(Runtime Library)就是WINDOWS系统给我们实现了C/C++的库函数的功能,提供的.LIB和.DLL文件。

其中.LIB是静态库,假如我们程序用.LIB去链接的话,意味着这个EXE里就包含了C/C++库函数的实现,运行的时候就不需要再依赖目标电脑上的运行库,方便拿到其他电脑跑。缺点呢,就是程序体积大。

.DLL则是动态库,选择动态链接的时候,EXE需要用到C/C++库函数的实现的时候,会去系统里面找相对应的DLL。多个程序也可以共享这一个DLL,带来的好处就是节省EXE的体积,但是拿到其他电脑去的话可能跑不起来,报错说:“找不到XXXXX.DLL”

我们用visual studio开发的时候,在项目属性里面可以看到有4种运行时库可选

运行库名称链接方式其他
MT静态
MTd静态Debug版本
MD动态
MDd动态Debug版本

2. 直观感受一下静态编译和动态编译的体积与依赖项目

用vs新建一个工程,简单写一个hello world的程序。

#include <iostream>
using namespace std;int main()
{cout << "Hello World" << endl;return 0;
}

然后分别用静态生成和动态生成:

由上面两个图片可以清晰地看出来:静态编译体积大,动态编译依赖多

3. VS运行时库包含哪些主要文件(从VS2015起)

库描述MTMTDMDMDd
通用C运行时库libucrt.liblibucrtd.lib

ucrt.lib

ucrtbase.dll

ucrtd.lib

ucrtbased.dll

VC运行库libvcruntime.liblibvcruntimed.lib

vcruntime.lib

vcruntime<version>.dll

vcruntimed.lib

vcruntime<version>d.dll

C++标准库libcpmt.liblibcpmtd.lib

msvcprt.lib

msvcp<version>.dll

msvcprtd.lib

msvcp<version>d.dll

初始化CRT的代码库libcmt.liblibcmtd.libmsvcrt.libmsvcrtd.lib

参考链接:C 运行时 (CRT) 和 C++ 标准库 (STL) .lib 文件 | Microsoft Learn

仔细留意一下【初始化CRT的代码库】,为什么动态生成的依赖库只有lib没有dll,官网说它的dll就是【通用C运行时库】和【VC运行库】的合集。这里有点难理解,也不知道为什么要这么设计呢?希望前辈们多多指教一下。

4. 动态库和静态库混用的情况

假如我们现在EXE使用动态编译,但依赖一个静态编译而成的LIB,可以吗?

试试!首先自己编译一个lib。头文件如下:

#pragma oncevoid StaticHello(); // 定义一个函数

源文件如下:

#include "my_mtd_lib.h"
#include <iostream>
using namespace std;// 实现头文件的函数
void StaticHello()
{cout << "----------" << endl;
}

生成选项用调试版的的静态库MTd

接着在其他工程调用这个LIB

#include <iostream>
using namespace std;#include "../my-mtd-lib/my_mtd_lib.h"
#pragma comment(lib, "../Debug/my-mtd-lib.lib")int main()
{cout << "**********" << endl;StaticHello(); // 调用my-mtd-lib.lib的函数return 0;
}

生成选项用调试版的动态库MDd

点生成报错:

1>libcpmtd.lib(wlocale.obj) : error LNK2005: "public: int __thiscall std::ios_base::flags(void)const " (?flags@ios_base@std@@QBEHXZ) 已经在 msvcprtd.lib(MSVCP140D.dll) 中定义
1>libcpmtd.lib(wlocale.obj) : error LNK2005: "public: __int64 __thiscall std::ios_base::width(__int64)" (?width@ios_base@std@@QAE_J_J@Z) 已经在 msvcprtd.lib(MSVCP140D.dll) 中定义
1>libcpmtd.lib(wlocale.obj) : error LNK2005: "public: __int64 __thiscall std::ios_base::width(void)const " (?width@ios_base@std@@QBE_JXZ) 已经在 msvcprtd.lib(MSVCP140D.dll) 中定义
1>libcpmtd.lib(xlocale.obj) : error LNK2005: "public: int __thiscall std::ios_base::flags(void)const " (?flags@ios_base@std@@QBEHXZ) 已经在 msvcprtd.lib(MSVCP140D.dll) 中定义
1>libcpmtd.lib(xlocale.obj) : error LNK2005: "public: int __thiscall std::basic_streambuf<char,struct std::char_traits<char> >::sputc(char)" (?sputc@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QAEHD@Z) 已经在 msvcprtd.lib(MSVCP140D.dll) 中定义
1>libcpmtd.lib(xlocale.obj) : error LNK2005: "public: __int64 __thiscall std::ios_base::width(__int64)" (?width@ios_base@std@@QAE_J_J@Z) 已经在 msvcprtd.lib(MSVCP140D.dll) 中定义
1>libcpmtd.lib(xlocale.obj) : error LNK2005: "public: __int64 __thiscall std::ios_base::width(void)const " (?width@ios_base@std@@QBE_JXZ) 已经在 msvcprtd.lib(MSVCP140D.dll) 中定义

报的都是同一个错:libcpmtd.libmsvcprtd.lib冲突,有符号重定义。再仔细看是不是很眼熟,刚好是前面 第三部分 表格里面【C++标准库】里面MTd和MDd,跟我们项目的设定一一对应。我对这个报错的理解是:链接阶段,main.obj会找到msvcprtd.lib里面关于cout的符号,也发现my-mtd-lib.lib也带了来自libcpmtd.lib的cout的符号,所以报重定义。

所以一个项目里面像我的例子这样混用两个运行时库,实际上大概率不行,理论上也不好。最优的做法当然是所有依赖都基于同一套运行时库。

5. 感谢清单

这篇文章是受到下面博主的文章指引启发的,感谢前辈的分享

你所不知道的C和C++运行库_vcc++运行库-CSDN博客

相关文章:

  • Python爬虫bs4的基本使用
  • mfc140u.dll缺失?快速解决方法全解析,解决mfc140u.dll错误
  • Harmony商城项目
  • SpringBoot日常:链路追踪skyworking的接入
  • MYSQL求月份同比数据和环比数据
  • 【步联科技身份证】 身份证读取与解析———未来之窗行业应用跨平台架构
  • 深度学习应用详解
  • 叶国富“推翻”马云新零售,零售新王此刻登基?
  • 线性基学习DAY2
  • 【libp2p——NAT】
  • ansible学习之 Facts
  • 平安养老险肇庆中心支公司开展“2024年金融教育宣传月”活动
  • matlab-批处理图像质量变化并形成折线图 (PSNR)
  • HarmonyOs 查看官方文档使用弹窗
  • 【C/C++】错题记录(二)
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • Idea+maven+scala构建包并在spark on yarn 运行
  • JDK 6和JDK 7中的substring()方法
  • k8s 面向应用开发者的基础命令
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • Map集合、散列表、红黑树介绍
  • MaxCompute访问TableStore(OTS) 数据
  • Mysql优化
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 小而合理的前端理论:rscss和rsjs
  • 06-01 点餐小程序前台界面搭建
  • k8s使用glusterfs实现动态持久化存储
  • # linux从入门到精通(三)
  • ###C语言程序设计-----C语言学习(3)#
  • #NOIP 2014# day.2 T2 寻找道路
  • #QT项目实战(天气预报)
  • (1)虚拟机的安装与使用,linux系统安装
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (12)Linux 常见的三种进程状态
  • (8)STL算法之替换
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (k8s)kubernetes 部署Promehteus学习之路
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (Matlab)使用竞争神经网络实现数据聚类
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (生成器)yield与(迭代器)generator
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (数据结构)顺序表的定义
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)jdk与jre的区别
  • .libPaths()设置包加载目录
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化