【C/C++开发】C语言 DLL(动态链接库)中申请动态内存释放的问题
参考:首先,声明一点,凡是使用malloc之类命令动态申请的内存,必须进行释放操作,否则就会发生内存泄漏问题。
DLL中申请的内存释放,如果没有做过,很可能会认为是直接在调用程序中释放就可以了,其实不然,如果真那么做了,会发现,程序总是不明不白的当掉。那么,如何释放DLL中申请的动态内存呢?
首先,说明一点,对于DLL,采用了一种保护机制,那就是,DLL中的任何对象都是对外隐藏的,虽然我们通过传址调用的方式,在调用过DLL之后,可以访问DLL中动态申请的内存空间,但是,我们的调用程序并不能释放这个空间,原因就是因为它是对外隐藏的,由于这个原因,我们也只是获得了访问这类空间的权利,如果真的要释放的话,还得要被调用的DLL本向来完成,所以,我们在编写DLL的时候,如果发生了动态内存申请,并且,由于这些动态申请的内存会被调用的父进程程序访问,DLL结束的时候,并不能立即释放这些动态内存,那么,这时就需要我们同时编写一个专门用来释放这些动态内存的函数,和DLL编译到一起,然后,在父进程程序使用完这些动态内存空间后,再以传址的方式,调用这个释放函数,这样就可以将这些DLL中申请的动态内存空间释放掉了。
例:
DLL:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
_declspec(dllexport) void testFunc(char **tmp)
{
*tmp = (char *)malloc(sizeof(char)*100);
memset(*tmp,'\0',100);
strcpy(*tmp,"susan");
}
_declspec(dllexport) freeTestFuncMemory(char **tmp)
{
if(NULL != *tmp)
{
free(*tmp);
}
}
上述两个DLL要编译到一个LIB库里。
DLL调用:
int main(int argc,char **args)
{
char *employeeName = NULL;
testFunc(&employeeName);
printf("%s\n",employeeName ); /* 这里会输出 susan */
freeTestFuncMemory((&employeeName);
printf("%s\n",employeeName ); /* 这里会输出乱码 */
}
实际应用的时候,一定要注意,调用完分配内存的函数后,最好马上用三方变量将动态内存的值接出去,然后马上调用释放函数,否则如果在释放前又调用了其它DLL,那么再释放的时候就会出问题。我这次应用比较急,就没有再细查解决方法,哪位朋友发现方法了,麻烦可以给小弟留个言,谢谢。
这个例子不是很完整,不过原理是没有问题的,参照的话,请自行补充。
---------------------------------------------------------------------------------------------------------------------------------------
2016-10-26 0:45
张朋艺 pyZhangBIT2010@126.com
关于动态链接库中动态申请的内存区域如何传递到用户空间:刚开始尝试用指针,比如在dll中申请了一个char*的一串内存区域。
于是就有了下面的几个疑惑:
1. 比如在一个dll中的初始化函数中申请了一块char*的内存,之后函数返回,那么这块用malloc申请的内存是谁在维护?操作系统接管之后会不会被乱用掉???因为后续还会针对这块内存进行处理,不希望操作系统对这块内存进行额外的操作!
2. 刚开始使用同样的char*变量从dll的导出函数中将这块内存的地址传出,但是好像不对,于是考虑到了以前使用函数进行参数传递的时候,要想传递比如10个int型的数据,那么传递int*的变量就可以了。传递的必须是地址,所以,对于char*的一篇内存,我要传递过去的话,实际上是应该使用char**,就是指针的指针,而不能使用char*。如果使用char*进行传递的话,比如在User定义了一个char* pData变量,该变量作为参数送入了DLL的导出函数中,然后该函数中对char* pData进行了赋值,赋值为DLL中动态申请的char*的首地址,那么实际上char*
pData的值并没有发生改变。对这个变量pData赋值,是没有用的,你得是对这个变量的存储地址进行赋值才有效,所以,必须对这个pData的存储地址进行赋值。还是有点乱,重新捋一下:对于传递好几个int型的变量的时候,传递的是int型变量的地址,通过操作它们的内存地址以达到传递int型变量的目的。操作地址赋值,就是往存储这个变量的地址上写入要传递的变量,才能达到真的传递参数的目的;那么说到这个char*的内存区域pMem,pMem实际上就等于这块内存空间的起始地址,那么我希望传递这个地址,是不是得通过(char*)*ppMem的地址上的内容才能传递呢?即*ppMem
= pMem即可,这个时候使用*ppMem就可以访问到这片内存区域了,具体的就是(*ppMem)[0,1,2....]。
目前对于第一个疑惑,还是不太清楚,DLL中malloc的内存,在函数返回后,操作系统会对这片内存如何处理?会不会有别的东西乱入这篇内存区域,导致我后续使用这篇内存区域的时候出现难以察觉的问题。
------
2016-10-26 1:12
张朋艺 pyZhangBIT2010@126.com
【C/C++开发】C语言 DLL(动态链接库)中申请动态内存释放的问题的更多相关文章
- 在DLL动态链接库中封装VCL的MDI子窗体
在DLL动态链接库中封装VCL的MDI子窗体不多说了,看代码就应该明白了,曾经我遇到的问题,现在放出来大家共享! 这里是工程文件的部分: 在DLL中封装MDI子窗体需要重写DLL入口函数,具体代码如下 ...
- VC 使用msxml6.dll动态链接库中的函数读写XML文件
VC 使用msxml6.dll动态链接库中的函数读写XML文件 目录 1 引言 2 .dll使用方法 3 常用函数总结 4 实例应用 5 运行效果预览 6 补充说明 7 不足之处 8 更新 引言: ...
- 第10课 C++中的动态内存分配
C++中的动态内存分配 C语言是通过库函数来完成动态内存分配的,而C++是通过关键字从语言层面支持的. C语言中的malloc是基于字节来进行内存申请的,C++中是基于类型来进行的. delete加上 ...
- 【C++】C++中的动态内存解析
目录结构: contents structure [-] 动态内存和智能指针 使用shared_ptr管理内存 使用new直接管理内存 shared_ptr和new结合使用 unique_ptr we ...
- 因内存释放而引发的中断问题,dll中new的内存释放问题
调试程序,每次关闭一个界面就会弹出中断错误. 为了确认这个问题,我将出现问题那一段代码中的函数一个个屏蔽,以此来确认到底哪个函数出现问题,缩小范围: 最后我发现,只要屏蔽掉checkIfFingerI ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 动态内存
栈:在函数内部声明的所有变量都将占用栈内存. 堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存. 可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址.这种运 ...
- C# DumpBin使用 查看反射C++ dll 动态链接库中的函数
DumpBin是Microsoft提供的一个用于查看.exe..dll文件信息的工具,其位于: C:\Program Files (x86)\Microsoft Visual Studio 10.0\ ...
- C语言的存储类别和动态内存分配
存储类别分三大类: 静态存储类别 自动存储类别 动态分配内存 变量.对象--->内存管理 内存考虑效率(时间更短.空间更小) 作用域 链接.---->空间 存储器 ----->时 ...
- c++中的动态内存分配
使用new和delete动态的分配和释放内存 使用new来分配新的内存块,通常情况下,如果成功,new将返回一个指针,指向分配的内存,否则将引发异常,使用new时,需要指定要为那种数据类型分配内存: ...
随机推荐
- P3254——DP&&入门
题目 给定一个$n \times m$的$01$矩形,选择其中为$1$的位置,要求互不相邻,问方案数. 解决方案 直接dp因为状态较多,数组很难直接表示出来,我们采用二进制状态压缩存储. 用$dp[i ...
- CCPC 2017 哈尔滨 D. X-Men && HDU 6233(思维+期望)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6233 题意:一个树上有m个人,每个人在某个节点上,每个时刻每个人可以和一个与他距离大于 1 的点进行交 ...
- Codeforces Round #589 (Div. 2) C - Primes and Multiplication(数学, 质数)
链接: https://codeforces.com/contest/1228/problem/C 题意: Let's introduce some definitions that will be ...
- Git始终忽略特定文件的某一行内容
笔者在编写Z Shell文件的时候经常会使用到set -x来开启调试,但不希望提交到仓库 解决方案 Git提供了一种文件过滤器,此方法可以帮助在提交时移除set -x 我们先来编写脚本,如何移除这一行 ...
- App自动化-python-Unittest框架
TestCase: 一段Testcase代码示例: # -*- coding: utf-8 -*- ''' Created on 2019-6-27 @author: adminstrator ''' ...
- 微信小程序开发入门教程(二)---分析官方云开发例子中的一些功能
接上一篇文章:https://www.cnblogs.com/pu369/p/11326538.html 1.官方云开发的例子中,点击获取 openid,对应代码在E:\wxDEV\helloyun\ ...
- 小米oj 不要乱改代码(并查集)
不要乱改代码 序号:#91难度:非常难时间限制:2000ms内存限制:50M 描述 最近小米公司内爆发了一种名叫"瞎改我代码就会死"的传染病. 传播方式是只要与染病者共同编辑过一 ...
- 【csp模拟赛2】 序列操作
线性推,开数组太麻烦,可以用指针 代码: #include <iostream> #include <cstdio> #include <queue> using ...
- #define定义宏函数 的正确使用
如何使用宏来定义一个自定义函数呢?首先我们来看下面这段代码 #define SQUARE(x) x*x int main() { int a = 5; printf("SQUARE(a): ...
- Mybatis-Plus BaseMapper自动生成SQL及MapperProxy
目录 Spring+Mybatis + Mybatis-Plus 自定义无XML的sql生成及MapperProxy代理生成 问题产生背景 框架是如何使用 无Xml的SQL是如何生成生成及SQL长成什 ...