msvc C++编译链接
C++编译链接
静态库编译
C RunTimeLibrary
C++是C的超集,C RunTimeLibrary 是 C 标准库,在编译期安装的时候,或者下载vc运行时库安装到电脑中。
msvc中/mt /mtd /md /mdd 是决定当前程序用哪个C RunTimeLibrary. 不同的实现不同。
链接过程
静态库链接过程是需要所有的lib文件。比如 A 静态库有 Hello 函数。 B 静态库使用 A 项目的 Hello 函数编译成 Hello World 函数,C 执行程序调用 B 的Hello World函数。
A.lib 会包含Hello函数的信息。
B.lib 会包含HelloWorld函数的信息。但没有Hello的函数。
C.exe 要链接exe的时候,需要 A.lib B.lib 才能真正链接成功。
当然还有一些默认的,比如 C RunTimeLibrary 的链接,也会参与进来。
当A.lib的 C RunTimeLibrary 与 B.lib 中C RunTimeLibrary的版本不匹配的时候,会报 error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MT_StaticRelease”不匹配值“MTd_StaticDebug”。 (如果没有调用 C 的函数,则不会报这个错,最常见的 #include ... 但是基本函数,只要有一个包含了,就会报错,所以必然出错)
原因是 在链接的过程中,C的函数有多种实现导致。所以同一个函数,无法定位真正是哪个RunTimeLibrary中的函数参与进来。
动态库编译
动态库编译成dll,是跟exe一样需要链接,链接一个可加载的动态库。所以一个dll中,包含所有引用的函数信息。
A.lib 静态库 b.lib b.dll 动态库(动态库项目也会生成一个lib符号文件,但没有实现,因为c++会在编译期间,把函数和类改名。)
b.dll 中就包含 Hello 函数的信息,当链接的时候,只需要链接 b.lib 即可。
c.exe 就只需要b.lib 和 b.dll 即可。
场景问题加深理解
下面场景都是使用了 RuntimeLibrary 库的情景(基本没有不用的)
因为exe必用 c 标准库的东西,所以链接的时候如果 /MD /MDD /MT /MTD 如果不匹配,都会报 RuntimeLibrary 不一致
3rd_release.lib -> engine.lib -> app.exe 3rd_release.lib 如果是静态库,并且是release,没有debug版本, 那 engine.lib 必须也是release版本的lib,否则在 app.exe 生成的时候会报 RuntimeLibrary 不一致。
debug 是可以链接 release 版本的代码库的,但是 debug A.exe 不能调用 额外的 debug B 库,B 调用 release.lib 会报 A.exe 的RuntimeLibrary和 release.lib 的不一致。
stl 不同debug release 的 许多变量的长度不一致,运行时会溢出闪退。
*.lib 库对应的宏和头文件使用应保持一致,因为编译时,已经根据宏 导出函数内容到 .lib 中,如果头文件声明跟 lib 中函数不一致,会导致 函数 link 不上。
class 的头文件函数(实现在头文件中), lib 中不会定义,基本大部分编译期,会直接把头文件函数变为内联函数,而且不用dllexport。
如果想使用 3rd_release.lib -> engine.lib -> app.exe engine 是debug库,可以用 engine.dll ,这样会在dll时候,就链接完成。
静态库函数保持一致,全局变量,静态变量都是一份。动态库会在链接的时候,把静态库的内容链接到dll中,两个dll链接一个静态库,则这个静态库中的全局变量和静态变量都是两份。如果宏定义不一致,则会爆炸。(可以想象,一个库改了静态变量,而另一个库的函数中没有改,导致实现有时好,有时坏。 心态爆炸)
vs 中如果不填 /md ... 等,填空,会默认 /mt /mtd (不一定,我测试是这样)
cpp中使用宏,头文件不使用的库,已经生成的lib 文件,链接的主体(exe)再怎么改 宏定义,也不会影响函数的实现(在编译的过程已经确定了,链接方再怎么改,也无济于事)
网上查的dll使用准则是,dll中的对象,不能传递到dll外,如果传出来,可能会调用到跟dll中预想不同的函数(因为dll的宏定义是在dll生成的时候,但是使用的人的dll和stl等标准库的实现不一致),导致整体流程损坏而查不到原因。 dll的对象是在dll中运转(减少错误发生率)
总结
如果没有想好的话,最好是不要使用dll,静态库只是编译慢,但会减少很多问题。 如果想要使用dll,则一定要注意项目链接和宏,还有对象的流转,还有dll链接的问题。
最好是,如果一个dll链接了一个静态库,则不导出这个静态库的任何头文件,所有想要操作这个静态库的,都需要通过dll的接口来调用。
gcc clang 等编译器,有些没有_DEBUG 宏,当跨编译器链接的时候,也可能会出现额外的问题。
而有些cmake工具会重写宏定义,如果通过vs创建项目,有些会定义默认的宏定义,但是cmake等工具,是直接写文件。导致不一定会跟vs等IDE一样生成默认的宏定义。则会导致编译的问题。
目前C++项目第三方都是开源的,或者会给debug版本,所以大部分都是自己公司的某个人写的(或者哪里编译出来的)才会导致只有release库文件。大多数是没有这个问题的。
msvc C++编译链接的更多相关文章
- ffmpeg+x264 Windows MSVC 静态编译
尝试ubuntu和win下mingw编译版本,但都在Vistual Studio链接时因为依赖 libgcc.a, libmingw.a, libmingwex.a 会与mscrt 有符号冲突. 最后 ...
- windows下使用mingw和msvc静态编译Qt5.15.xx
windows下使用mingw和msvc静态编译Qt5.15.xx 下载并安装相关依赖软件 Python version 2.7 https://www.python.org/downloads/ ( ...
- 加快XCode的编译链接速度(200%+)—XCode编译速度慢的解决方案
最近在开发一个大项目的时候遇到一个很头疼的问题,由于项目代码较多,每次都要编译链接1分钟左右,调试的时候很浪费时间,于是研究了一下如何提高编译链接的速度,在这里分享给大家. 提升编译链接的速度主要有以 ...
- C++开始前篇,深入编译链接(3)
一,COMMON块 什么是COMMON块,这是一种机制,早期的Fortran没有动态分配空间的机制,程序员必须事先声明它所需要的临时使用空间的大小.Fortran把这种空间叫做COMMON块,当不同的 ...
- C++开始前篇,深入编译链接
C++开始,为什么要写这个东西,因为按照课堂进度的话,现在的C++已经学到模板以及重载了,有时却仍然因为一些小问题无法解答,原因是忘记了开始时学到的知识,深知不能像猴子掰棒子一样,掰一个扔一个,因此, ...
- VS编译链接时错误(Error Link2005)的解决方法
近期参与的项目中使用了公司另外一个同事提供的一个静态库文件.该静态库文件集成了CUDA, OpenCL两个库,用于做图形加速计算,提高视频解码拼接速度.但是在编译链接项目时,VS爆出如下错误: 1&g ...
- GCC编译器编译链接
在gcc编译器环境下,常见的文件扩展名的含义如下: .c:C源程序,经过预编译后的源程序也为.c文件,它可以通过-E参数输出. .h:头文件 .s:经过编译得到的汇编程序代码,它可以通过-S参数输出. ...
- C语言编译链接
转载请标明: 编译链接是使用高级语言编程所必须的操作,一个源程序只有经过编译.链接操作以后才可以变成计算机可以理解并执行的二进制可执行文件. 编译是指根据用户写的源程序代码,经过词法和语法分析,将高级 ...
- C++常见gcc编译链接错误解决方法
除非明确说明,本文内容仅针对x86/x86_64的Linux开发环境,有朋友说baidu不到,开个贴记录一下(加粗字体是关键词): 用“-Wl,-Bstatic”指定链接静态库,使用“-Wl,-Bdy ...
- linux 编译,链接和加载
1. 序 最近在折腾各种.so,碰到了一些问题,一开始对于很多错误也没有头绪,茫然不知所措.索性化了一天多时间将<<程序员的自我修养—链接.装载与库>>中部分内容略读了一遍 ...
随机推荐
- hackathon 复盘:niche 海外软件工具正确的方法 6 个步骤
上周末,去参加了北京思否 hackathon,两天时间内从脑暴 & 挖掘软件 IDEA -> Demo 研发路演,这次经历让我难忘.这里我的看法是每个开发者圈友,都应该去参加一次 hac ...
- [Pytorch框架] 2.4 卷积神经网络简介
文章目录 2.4 卷积神经网络简介 2.4.1 为什么要用卷积神经网络 2.4.2结构组成 卷积层 卷积计算 卷积核大小 f 边界填充 (p)adding 步长 (s)tride 计算公式 卷积层 激 ...
- python自产调试工具pdb的使用
python自产调试工具pdb的使用 介绍 调试打印在写代码的时候不可避免 项目越大,调试可能花的时间会越多 print调试可能是最早用的,一段时间内你都会习惯这种方式 一旦成了老鸟,你应该会去用ID ...
- ai问答:vue3+pinia+WebSocket 封装断线重连(实战)
把socket实例 挂载到全局 为方便梳理,请忽略typescript # main.ts import {createApp} from 'vue' import App from './App.v ...
- IIS6网站批量迁移至IIS7经验分享
迁移原因:公司服务器更换 迁移环境:源服务器 windows2003 X86 IIS6 目标服务器:windows2008 X64 IIS7 迁移过程: 第一次迁移失败,作为简要记 ...
- OpenResty学习笔记03:再探WAF
一. 再谈WAF 我们上一篇安装的WAF来自另一位技术大神 赵舜东,花名 赵班长,一直从事自动化运维方面的架构设计工作.阿里云MVP.华为云MVP.中国SaltStack用户组发起人 .新运维社区发起 ...
- python Unitest和pytest 介绍和安装
前言 目前有两种纯测试的测试框架,pytest和unittest,这系列文章主要介绍pytest为主 UnitTest测试框架理论 python 自带的单元测试框架,常用在单元测试 在自动化测试中提供 ...
- Win10系统Anaconda下tensorflow的GPU环境搭建
我的环境:Win10 + Anaconda + tensorflow-gpu1.14 + CUDA10.0 + cuDNN7.6 + python3.6 注意:tensorflow版本.CUDA版本. ...
- 2021-07-08:股票问题5。给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票)
2021-07-08:股票问题5.给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 .设计一个算法计算出最大利润.在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票) ...
- Redis数据结构二之SDS和双向链表
本文首发于公众号:Hunter后端 原文链接:Redis数据结构二之SDS和双向链表 这一篇笔记介绍一下 SDS(simple dynamic string)和双向链表. 以下是本篇笔记目录: SDS ...