小心DLL链接静态库时的内存错误
最近写的模块,在独立的应用程序中测试是没问题的,但把它装配成DLL后,再在另一个应用程序中调用时却出现了内存错误。程序的模块链接关系大概是这样的:
module就是我所写的模块,在这里被封装为DLL,因为要使用json相关的功能,该DLL链接了一个静态库 (jsoncpp.lib)。最后在应用程序中导入并使用module.dll,同时因为在应用程序中也需要用到json,所以应用程序也链接了jsoncpp.lib。
以下用一些伪代码来描述这些模块间的调用关系,以具现出这个错误。
jsoncpp.lib为c++提供了功能齐全的json操作,其核心的类是Json::Value。(阅读本篇文章你无需了解太多json)
module.dll中导出了一个接口:
//ModuleClass.h
#include "json/value.h"#if defined MODULE_EXPORTS
#define MODULE_EXPORTS __declspec(dllexport)
#else
#define MODULE_EXPORTS __declspec(dllimport)
#endifclass ModuleClass
{
public:MODULE_EXPORTS void AllocSomeMemory( Json::Value &root ){// 这将申请一些内存,因为会new出一个Json::Value,并append到root上root.append( "testString" );}
};
应用程序:
1
|
#include "json/value.h"
|
2
|
#include "ModuleClass.h"
|
3
|
int main()
|
4
|
{
|
5
|
Json::Value root;
|
6
|
ModuleClass::AllocSomeMemory( root );
|
7
|
}
|
在Debug模式下,当main函数执行完毕,对Json::Value root进行析构时,程序便出现了异常。分析下,很显然,调用ModuleClass::MallocMemoryHere时申请的内存,是在module.dll中申请的,而对这些内存的析构则是在应用程序(.exe)中进行的(析构root会同时析构append在root上的所有子Json::Value)。不过,这是异常的真正原因么?追踪到异常的出错点:dbgheap.c文件中那句ASSERT语句。
1
|
/*
|
2
|
* If this ASSERT fails, a bad pointer has been passed in. It may be
|
3
|
* totally bogus, or it may have been allocated from another heap.
|
4
|
* The pointer MUST come from the 'local' heap.
|
5
|
*/
|
6
|
_ASSERTE(_CrtIsValidHeapPointer(pUserData));
|
注释中的最后一句话”The pointer MUST come from the ‘local’ heap“引起了我的警惕,难道对于内存的申请和释放不是在同一个heap上,除了‘local’ heap还有一个什么heap么。去MSDN上搜索了关于_CrtIsValidHeapPointer,似乎找到了答案,以下这段话是MSDN上对于_CrtIsValidHeapPointer的介绍:
The _CrtIsValidHeapPointer function is used to ensure that a specific memory address is within the local heap. The local heap refers to the heap created and managed by a particular instance of the C run-time library. If a dynamic-link library (DLL) contains a static link to the run-time library, it has its own instance of the run-time heap, and therefore its own heap, independent of the application’s local heap. When _DEBUG is not defined, calls to _CrtIsValidHeapPointer are removed during preprocessing.
注意字体加粗的部分,这不正应对我的情形么?!错误不在于DLL中申请的内存在EXE中释放,而在于如果这个DLL拥有一个静态链接,它就会拥有独立的运行时堆,独立于应用程序的堆。这样对于内存申请和释放并不是在同一个堆上进行的,当然出错了。解决:虽然MSDN上最后说,如果把项目改成release的,这个ASSERT就将避免,但这是放纵内存泄露,最好的解决办法是将静态链接也改成动态链接,这样就使得DLL能够和应用程序共享同一个堆,错误也得以避免。于是,我修改了jsoncpp的项目配置,生成jsoncpp的动态链接库,而不是使用静态库,重新导入到module.dll中,错误解决。
小心DLL链接静态库时的内存错误相关推荐
- 链接静态库时__imp_前缀错误
visual studio 中链接静态库, 出现找不到 __imp_函数名 的错误, extern "C"也增加了 找到一段 Logically, the next questio ...
- 链接静态库的顺序问题
在链接静态库时,如果多个静态库之间存在依赖关系,则有依赖关系的静态库之间存在顺序问题,这个在使用静态库时,需要注意,否则会报符号找不到问题,举例: libb.a依赖于是liba.a,而可执行文件tes ...
- 动态库、静态库编译测试:含静态库链接动态库、静态库,动态库链接静态库、动态库
本文的目的是测试各种类型库的编译后的使用效果,包括库又链接其他库的编译方法,使用方法,依赖性等. 太长不看版:请跳至文章最后的总结对比表. 一.内容包含: ①静态库libbb.a依赖静态库libaa. ...
- 因链接静态库先后顺序不正确,引起符号定义找不到
问题 项目中需要链接多个静态库,在编译的时候报错如下 sdi_io.cpp:(.text._ZN13sdi_H264EncIO7DataPopEPm+0x30):对'H264ENC_StatusGet ...
- [转]在Visual C++中以错误的顺序链接 CRT 库和 MFC 库时出现 LNK2005 错误
症状 当 C 运行时 (CRT) 库和 Microsoft 基础类 (MFC) 库的链接顺序有误时,可能会出现以下 LNK2005 错误之一: nafxcwd.lib... 当 C 运行时 (CRT) ...
- [iOS] 引用外部静态库时,(类别)目录方法无法加载问题
[iOS] 引用外部静态库时,目录方法无法加载问题 这个 bug 在 xcode 4.3 以下会出现,4.3 以后已经修正了. 解决方法为:找到 target 的图标,更改其 Other Linker ...
- linux下编译自己的静态库时依赖其他的动态库,使用时出现“undefined reference to”
对于我这个刚入IT行业不就得新手来说,在linux下链接库的时候总是会遇到各种各样奇葩的问题,最多的就是"undefined reference to"和"cannot ...
- 链接静态库时报can not be used when making a PIE object; recompile with -fPIE
链接了一个SDK的静态库,报了大量的错误都是 can not be used when making a PIE object; recompile with -fPIE 后在编译选项中加了-no-p ...
- 安装VC++2015运行库时出现0x80240037错误(JT预览报错)
[JT预览报错]原因是缺少C++2015运行库. [安装VC++2015运行库时出现0x80240037错误]原因是windows7系统缺少Windows6.1-KB2999226-x64.msu补丁 ...
最新文章
- 实战:基于深度学习和几何的3D边界框估计
- 指针的运用与strcpy函数的优化
- 斐波那契数列与阶乘---递归实现
- java io 读取多个对象_Java IO系列(五):读写对象ObjectOutputStream和ObjectInputStream详解...
- php vue联动查询,使用vue.js实现联动效果的示例代码
- git提交代码到自己的分支,并合并到主分支的完整流程。
- 编译Mysql 5.5时报do_abi_check错误
- 【面向对象】可变对象和不可变对象
- 这42个Python小例子,太走心~
- Python+django网页设计入门(8):网站项目文件夹布局
- LeetCode刷题(28)
- linux测试dvi接口,TeX Live DVI字体数据解析整数溢出漏洞
- jQuery实现瀑布流
- mysql期末作业_MySql期中作业
- Java cipher加密与解密
- 【python】注意力机制代码
- MySQL 是如何归档数据的呢?
- 声纳--成像声呐目标检测与跟踪技术研究 ---15年,哈工程,博士毕业论文
- 最新PHP/SG11扩展解密视频教程分享
- 用事实说话,我是如何快速入门一个新领域的
热门文章
- python语言变量随时声明_2. Go语言五种变量创建的方法
- 【渝粤教育】国家开放大学2018年春季 0105-21T酒店营销实务 参考试题
- [渝粤教育] 西南科技大学 投资经济学 在线考试复习资料(2)
- java如何通过grpc连接etcd_grpc通过 etcd 实现服务发现与注册-源码分析
- linux 命令行 解密,解密Linux终端命令 学好Linux
- 杀java_java怎么杀掉java进程
- oracle java 并发_【转】JAVA并发教程(ORACLE官网资料)
- NOIP模拟测试49·50「养花·折射·画作·施工·蔬菜·联盟」
- 在idea下开发出现404错误
- 【BZOJ1814】Ural 1519 Formula 1 插头DP