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

本文主要是探讨关于在动态链接库分配的内存在主程序中释放所产生的问题,该问题是我在刚做的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. iOS 9 之后更改状态栏字体颜色

    设置statusBar的[前景部分] 简单来说,就是设置显示电池电量.时间.网络部分标示的颜色, 这里只能设置两种颜色: 默认的黑色(UIStatusBarStyleDefault) 白色(UISta ...

  2. From MSI to WiX, Part 4 - Features and Components by Alex Shevchuk

    Following content is directly reprinted from : http://blogs.technet.com/b/alexshev/archive/2008/08/2 ...

  3. 类似QQ的应用毗邻(Pilin)即时聊天源码

      这个应用是从安卓教程网分享过了的,个人觉得这个还是挺不错的,毗邻(Pilin)即时聊天应用源码,承诺的 基于xmpp openfire asmack 的即时聊天应用,继续完善,现在只完成了文字.表 ...

  4. TCP/IP协议简单介绍

    TCP/IP协议族总共分为四层,分别为:          应用层:应用层协议有Telnet(远程登入协议).FTP(文件传输协议).SMTP(简单邮件传送协议).SNMP(简单网络管理协议).HTT ...

  5. Eclipse必须掌握的快捷键

    Eclipse快捷键 Ctrl +  / 添加//注释.删除//注释 Ctrl + 1 快速修复错误 Ctrl + Shift + f 格式化文档 Shift + Enter Shift + Ctrl ...

  6. bind()实现

    bind()函数是在 ECMA-262 第五版才被加入:它可能无法在所有浏览器上运行.这就需要我们自己实现bind()函数了 简单实现bind()方法: Function.prototype.bind ...

  7. DTCMS规格统一赋值

    admin\article_edit.aspx 已经存在 市场价格 和销售价格统一赋值 //赋值规格市场价格 $("#field_control_market_price").bl ...

  8. NPOI Excel导入 导出

    添加引用 using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using System; using System.Collections.Gene ...

  9. ASP.NET 将DataTable解析成JSON简介

    这里解析json使用的是Newtonsoft.Json.dll程序集.下面请看code: using System; using System.Collections.Generic; using S ...

  10. 提高SQL查询效率的常用方法

    提高SQL查询效率的常用方法 (1)选择最有效率的表名顺序(只在基于规则的优化器中有效): Oracle的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driv ...