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,碰到了一些问题,一开始对于很多错误也没有头绪,茫然不知所措.索性化了一天多时间将<<程序员的自我修养—链接.装载与库>>中部分内容略读了一遍 ...
随机推荐
- 做个清醒的程序员之拥抱AI
阅读时长约 13 分钟,共计约 3100个字. 昨天我体验了AI自动生成短视频,具体说来,首先我在域名为FreeGPT的免费网站,向它提问,然后生成一段文字.之后呢,再用剪映里面的"图文成片 ...
- VUE3企业级项目基础框架搭建流程(2)
typescript安装 这里使用的vue项目语言为:TypeScript,不了解的可以先去学习一下.TypeScript中文网 正常情况下安装typescript的命令为: // 全局安装 npm ...
- 零样本文本分类应用:基于UTC的医疗意图多分类,打通数据标注-模型训练-模型调优-预测部署全流程。
零样本文本分类应用:基于UTC的医疗意图多分类,打通数据标注-模型训练-模型调优-预测部署全流程. 1.通用文本分类技术UTC介绍 本项目提供基于通用文本分类 UTC(Universal Text C ...
- python-pygal
准备写大作业的时候发现了一个绝绝子的python库. 原文:https://blog.damavis.com/en/creating-vector-graphics-with-python/ 官网:h ...
- 这可能是最全面的Redis面试八股文了
Redis连环40问,绝对够全! Redis是什么? Redis(Remote Dictionary Server)是一个使用 C 语言编写的,高性能非关系型的键值对数据库.与传统数据库不同的是,Re ...
- JS Bom(window)对象
window 是客户端浏览器对象模型的基类,window 对象是客户端 JavaScript 的全局对象.一个 window 对象实际上就是一个独立的窗口,对于框架页面来说,浏览器窗口每个框架都包含一 ...
- 痞子衡嵌入式:聊聊i.MXRT1xxx上第三级启动保障 - SDMMC manufacture模式
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1xxx上第三级启动保障 - SDMMC manufacture模式. 如果你在 i.MXRT1xxx 板卡上尝试过从 SD ...
- 如何将c#在线编辑器嵌入自己项目
如何将c#在线编辑器嵌入自己项目 首先我们需要介绍一下这个在线编辑器,当前的在线编辑器支持c#的代码编译运行,并且无需后台服务,基于WebAssembly实现的在浏览器端去执行我们的c#代码,基于Ro ...
- 2020-10-27:go中select的执行流程是什么?
福哥答案2020-10-27: ***[2020-10-27:go中select的执行流程是什么?](https://bbs.csdn.net/topics/398044569)
- 2022-05-11:k8s安装easydarwin流媒体服务器,yaml如何写?
2022-05-11:k8s安装easydarwin流媒体服务器,yaml如何写? 答案2022-05-11: yaml如下: apiVersion: apps/v1 kind: Deployment ...