| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 记 QT 应用开发中的一个二进制兼容性问题 -> 正文阅读 |
|
[C++知识库]记 QT 应用开发中的一个二进制兼容性问题 |
笔者在参与开发一个集成了 QT 的跨平台桌面应用程序,目标平台是 Windows 和 Mac。一段时间以来,运行 Windows 平台的应用程序时,不断地被类似于如下这样的崩溃问题所折磨。 这里提示说,在 C++ Runtime 库中发生了崩溃,C++ Runtime 库中的一个断言失败了,即断言 从发送崩溃的这段代码中,基本上看不出任何线索。 通过 Visual Studio 查看这个崩溃发生的调用堆栈,找到这个堆栈中最靠近栈顶的我们自己编写的代码,可以看到这个崩溃发生在如下函数中:
这个 崩溃发生的具体位置如下: 即在 lambda 表达式返回的第 200 行发生了崩溃。代码本身,实在是看不出来有任何问题。 笔者想知道,是不是这里的 lambda 真有什么问题。于是笔者做了一个实验,移除上面这个函数中的几乎所有代码,只保留如下这一行:
再次运行 QT 应用程序,执行到这个函数时,崩发溃依然生。这种崩溃发生之莫名其妙,简直是让人怀疑人生。这次崩溃的具体位置如下图中 Visual Studio 的箭头所指的位置: 如图所示,崩溃发生在函数执行结束时的第 197 行。 这,其实是一个二进制兼容性问题。跨二进制编译目标传递对象时,有风险出现。比如一个动态链接库创建的对象,传给了另一个动态链接库来销毁。或者动态链接库创建了一个对象,但在应用程序中销毁了。 二进制兼容性问题的类型可能有很多。对象的创建和销毁在不同的二进制目标中导致的二进制兼容性问题可能也有不少。但就这个问题来说,出现二进制兼容性问题的原因在于 C++ MSVC 运行时库,即两个编译目标在编译链接时链接了不同的 C++ MSVC 运行时库。 C++ MSVC 运行时库会执行一些诸如内存分配与释放之类的操作。Windows 有动态 MSVC 运行时库和静态 MSVC 运行库时之分。Windows 平台的 C/C++ 程序,需要链接动态 MSVC 运行时库时,加 “/MDd” 或 “/MD” 编译标记(其中前者为 debug 版,后者为 release 版),需要链接静态 MSVC 运行时库时,加 “/MTd” 或 “/MT” 编译标记(其中前者为 debug 版,后者为 release 版)( 动态 MSVC 运行时库和静态 MSVC 运行时库在不同的堆中分配内存。大体可以理解为,链接静态 MSVC 运行时库时,每个编译目标都有一个堆,如每个动态链接库有自己的堆,可执行文件也有自己的堆;链接动态 MSVC 运行时库时,则是所有链接动态 MSVC 运行时库的各个编译目标共用同一个堆。 当编译应用程序和动态链接库时链接了不同的 MSVC 运行时库,而又在两者之间共同管理了对象的生命周期,则会出现我们这里遇到的崩溃。在这里,QT 链接了动态 MSVC 运行时库,我们的可执行程序链接了静态 MSVC 运行时库。这段代码中,QT 创建了一个 如此说来,两个同时链接动态 MSVC 运行时库的编译目标可以共同管理对象的生命周期,因为它们共用同一堆。而链接了静态 MSVC 运行时库的编译目标,不能与其它编译目标共同管理对象的生命周期,无论另一个编译目标链接的是静态 MSVC 运行时库,还是动态 MSVC 运行时库。 如此,解决问题的办法也就明了了。使用了 QT 的程序,最好链接动态 MSVC 运行时库。我们为我们的应用程序添加链接动态 MSVC 运行时库的编译标记:
如果一个动态链接库, 对于上面的这种问题,还有一种解决的思路,即严格遵守谁创建的对象谁释放的原则。一个动态链接库开出了创建对象的接口,则同时也必须开出释放对象的接口。 在 Stackoverflow 上有一个问题在讨论这个,Debug Assertion Failed! Expression: __acrt_first_block == header ,有兴趣的也可以参考一下。 参考文档 Debug Assertion Failed! Expression: __acrt_first_block == header |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 2:06:11- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |