动态链接库中分配内存引起的

本文主要是探讨关于在动态链接库分配的内存在主程序中释放所产生的问题,该问题是我在刚做的PJP工程中所遇到的,由于刚碰到之时感动比较诡异(这也是学识不够所致),所以将它写下来,大家一起分享.

问题来由:

由于该工程中要用到声音,所以我的分工之一就是用DirectMusic和DirectSound来开发声音播放的动态库,以提供给该工程的两个部分:仿真控制部分( 语音 )和三维部分( 场景声音 )使用,两个工程中的声音都以单独的线程播放,且两个线程几乎相同.,然而该动态库在以前的运行中一直没有出现过问题, 直到工程开发即将要结束阶段的前一个星期,我碰才到了这个问题,首先是三维部分中声音在第一次播放是没有问题,在播放第二个声音就出了问题(老是这样),但是仿真控制部分还是没有出现问题,我查不出错误,就用前一天的三维的版本来运行,重新生成后声音播放没有问题,初步以为是我同事当天写的代码有问题,可是第二天,同样的问题又发生了,还是那样,三维有问题,仿真部分没问题,怎么回事呢?我将三维的声音线程写成和仿真部分一样的,还是三维出问题,仿真没问题.我不相信是动态库中出问题,同一个动态库,同样的代码,只是在两个不同的程序里,为什么一个出问题,而另一个不出问题呢?

出错信息如下:

windows已在PowipD.exe中触发一个断点.
                  其原因可能是堆被损坏,这也说明PowipD.exe中或它所加载的任何DLL中有bug.
                  输出窗口可能提供了更多诊断信息

按下中断后输入窗口出现的信息如下:

HEAP[PowipD.exe]:Invalid Address specified to RtlValidateHeap( 01CC0000, 03723758 )
               Windows已在PowipD.exe中触发一个断点.
               输出窗口可能提供了更多诊断信息

由于这些原因让我迷惑不解,到底是为什么出现这种奇怪的事情呢?问题出在那里?

问题的解决:

简单地说:DLL中分配的内存DLL要负责释放!(一个模块分配的内存要在同一个模块中释放!)

找到解决方法后我查看了三个工程的设置(三个工程皆用VS2005开发):

三维:使用MDd(多线程调试DLL)运行期库

仿真控制:使用MTd(多线程调试)运行期库

声音动态库:使用MDd(多线程调试DLL)运行期库

于是,我将三个工程皆改为:使用MDd(多线程调试DLL)运行期库时,问题解决。

但是如果三个工程中有的不是用C/C++写的,或者其中有工程的设置已经不便更改了,那又有什么办法呢?

该问题主要是关于DLL与进程的地址空间的问题(下面是<<核心编程>>中的一段话):

单个地址空间是由一个可执行模块和若干个DLL模块组成,这些模块中,有些可以链接到静态版本的C/C++运行期库, 有些可以链接到一个DLL版本的运行期库,而有些模块(如果不是用C/C++编写的话)则根本不需要C/C++运行期库,许多开发人员经常会犯一个常见的错误,因为他们忘记了若干个C/C++运行期库可以存在于单个地址空间中.请看下面的代码(下面代码不是书上的):

DLL中如下:

int *DllFunc()

{

int *p = new int;

return p;

}

EXE中如下:

void EXEFunc()

{

int *p = DllFunc();

if( p!= NULL )

delete p;

}

如何看待这个问题呢?上面的代码能够正确运行吗?DLL函数分配的内存是由EXE的函数释放的吗?答案是可能的.上面显示的代码并没有提供足够的信息.如果EXE和DLL都链接到DLL的C/C++运行期库,那么上面的代码将能够很好地运行.但是,如果两个模块中的一个或者两个链接到静态C/C++运行期库,那个对delete的操作就会失败.

一个很方便的方法可以解决这个问题.当一个模块提供一个用于分配内存块的函数时,该模块也必须提供相应的释放内存的函数,将上面的代码改成如下的样子就不会出错了:

DLL中如下:

int *DllFunc()

{

int *p = new int;

return p;

}

void DLLDelete( int *p)

{

if( p != NULL )

delete p;

}

EXE中如下:

void EXEFunc()

{

int *p = DllFunc();

DLLDelete( p );

}

这样的代码才是正确的,当我将代码改成如上类似后,再将三维的运行期库改为原来一样(使用MDd(多线程调试DLL)运行期库),三维的声音也正确无误地播放出来了。当你在编写一个模块时,你时刻都得记着,别人的代码不一定是用C/C++写的,也有可能不能同时链接到DLL的C/C++运行期库。malloc和free函数也有类似的问题。

当然在你在生成你的模块时是可以选择运行期库的,VC 6.0配有6个运行期库:其描述如下:

库名

描述

LibC.lib

用于单线程应用程序的静态应用程序的静态链接库

LibCD.lib

用于单线程应用程序的静态链接库的调试版

LibCMt.lib

用于多线程应用程序的静态链接库的发行版

LibCMtD.lib

用于多线程应用程序的静态链接库的调试版

MSVCRt.lib

用于动态链接MSVCRt.dll库的发行版的输入库

MSVCRtD.lib

用于动态链接MSVCRtD.dll的调试版的输入库。该库同时支持单线程应用程序和多线程应用程序

而VS2005中只配了4个C/C++运行期库,就是上表中的后面4个。

建议各位在软件开发时同一软件的不同模块最好使用一致的运行库,否则还可能出现链接问题。

动态链接库中分配内存引起的问题-- windows已在XX.exe中触发一个断点的更多相关文章

  1. Windows 已在 DImageProcess.exe 中触发一个断点。

    其原因可能是堆被损坏,这说明 DImageProcess.exe 中或它所加载的任何 DLL 中有 Bug. 原因也可能是用户在 DImageProcess.exe 具有焦点时按下了 F12. 输出窗 ...

  2. xx.exe 中的 0x7c92e4df 处最可能的异常: 0xC0000008: An invalid handle was specified

    今天遇到个超级奇怪的问题,昨天还好端端的程序,今天用VS打开后,在关闭主窗口的时候居然弹出错误提示:xx.exe 中的 0x7c92e4df 处最可能的异常: "0xC0000008: An ...

  3. 中触发一个断点 其原因可能是堆被损坏,这说明 ***.exe 中或它所加载的任何 DLL 中有 Bug

    软件中使用了DevComponents.DotNetBar2.dll MessageBoxEx.Show("ddd");运行到这句出现这个错误 : 中触发一个断点 其原因可能是堆被 ...

  4. xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突(当指针访问异常时,应考虑是不是对象未创建)。

    xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突

  5. c语言中-----分配内存函数

    原型: void * realloc(void *p, size_t  size); realloc 可以对给定的指针所指的空间进行扩大 或者 缩小, 原有内存的数据保持不变.当然,对于缩小,则缩小部 ...

  6. 有未经处理的异常(在 xx.exe 中): 堆栈 Cookie 检测代码检测到基于堆栈的缓冲区溢出。

    一般这个问题是数组越界. 我产生这个异常的代码是这句:memcpy(tmp_cert.byKey, m_row[2], 255); 255的长度超过了char数组tmp_cert.byKey的长度.

  7. windows进程中的内存结构[转载]

    在阅读本文之前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基础知识. 接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变 ...

  8. windows进程中的内存结构(好多API,而且VC最聪明)

    在阅读本文之前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基础知识.   接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这 ...

  9. windows进程中的内存结构(缓冲溢出原理)

    接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论.下文中的C语言代码如没有特别声明,默认都使 ...

随机推荐

  1. TSQL基础(三)

    字符处理函数 sql中常见的字符类型有: char(n) --长度固定 不可变 非Unicode 字符数据 n 必须是一个介于 1 和 8,000 之间的数值 nchar(n) --长度固定 不可变 ...

  2. 个人常用jq方法复习

    $("#elem").on({ mouseover:function(){}, mouseout:function(){}, }); $(ele).closest("di ...

  3. day 0.

    /* 嗯 就要结束了. OI生涯 2015.12-2016.11. 认识了很多人. 然后我这个学渣跟你们混在一起 感觉自卑至极啊. 好了 先不说这些伤心的话. Gryz小伙伴儿们NOIP RP++吧. ...

  4. 进度条轮播【BackgroundColor】

    直接贴代码先看 HTML: <div class="bannar"> <div class="img"> <ul> < ...

  5. hibernate导入大量数据时,为了避免内存中产生大量对象,在编码时注意什么,如何去除?

    Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( i ...

  6. angularJs--$on、$emit和$broadcast的使用

    $emit只能向parent controller传递event与data $broadcast只能向child controller传递event与data $on用于接收event与data 例子 ...

  7. json 语义分析

    json 中:元素与值用冒号 ":" 隔开元素与元素用逗号 "," 隔开{} 之间是一个对象, 对象可以层层嵌套[] 表示数组, 数组元素用逗号 ", ...

  8. EditorLineEnds.ttr 受影响的D版本 Delphi 8-2010

    http://stackoverflow.com/questions/25295980/delphi-2006-2010-error-cannot-create-file-c-users-admin- ...

  9. java----线程篇

    一个线程是进程内的一个单一的顺序控制流程图,多线程是指一个进程可以同时运行几个任务,每个任务由一个线程来完成.即多个线程可以同时运行,并且在一个进程内执行不同的任务. 1.创建线程两种方法方法一, 继 ...

  10. DHT网络第一部分研究结果 加入长期在线的node

    源码:http://jijiea.com/upfile/DHT_Part1_How_To_Join_In_DHT.zip