动态链接库中分配内存引起的问题-- windows已在XX.exe中触发一个断点
动态链接库中分配内存引起的
本文主要是探讨关于在动态链接库分配的内存在主程序中释放所产生的问题,该问题是我在刚做的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中触发一个断点的更多相关文章
- Windows 已在 DImageProcess.exe 中触发一个断点。
其原因可能是堆被损坏,这说明 DImageProcess.exe 中或它所加载的任何 DLL 中有 Bug. 原因也可能是用户在 DImageProcess.exe 具有焦点时按下了 F12. 输出窗 ...
- xx.exe 中的 0x7c92e4df 处最可能的异常: 0xC0000008: An invalid handle was specified
今天遇到个超级奇怪的问题,昨天还好端端的程序,今天用VS打开后,在关闭主窗口的时候居然弹出错误提示:xx.exe 中的 0x7c92e4df 处最可能的异常: "0xC0000008: An ...
- 中触发一个断点 其原因可能是堆被损坏,这说明 ***.exe 中或它所加载的任何 DLL 中有 Bug
软件中使用了DevComponents.DotNetBar2.dll MessageBoxEx.Show("ddd");运行到这句出现这个错误 : 中触发一个断点 其原因可能是堆被 ...
- xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突(当指针访问异常时,应考虑是不是对象未创建)。
xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突
- c语言中-----分配内存函数
原型: void * realloc(void *p, size_t size); realloc 可以对给定的指针所指的空间进行扩大 或者 缩小, 原有内存的数据保持不变.当然,对于缩小,则缩小部 ...
- 有未经处理的异常(在 xx.exe 中): 堆栈 Cookie 检测代码检测到基于堆栈的缓冲区溢出。
一般这个问题是数组越界. 我产生这个异常的代码是这句:memcpy(tmp_cert.byKey, m_row[2], 255); 255的长度超过了char数组tmp_cert.byKey的长度.
- windows进程中的内存结构[转载]
在阅读本文之前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基础知识. 接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变 ...
- windows进程中的内存结构(好多API,而且VC最聪明)
在阅读本文之前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基础知识. 接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这 ...
- windows进程中的内存结构(缓冲溢出原理)
接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论.下文中的C语言代码如没有特别声明,默认都使 ...
随机推荐
- DOS批处理命令-SET命令
SET是专门用来创建.设置.查看或删除环境变量. 总结了下,SET的使用语法一般有下面几种 1.SET 变量名=变量值 这边有一点要注意的,就是变量名和变量值中间的等号两端不需要也不能有空格 看看下面 ...
- 基于DIV+ul+li实现的表格(多示例)
一个无序列表biaoge,前四个列表项我们赋予了类biaotou.因为这四个项是表格头部,应该与表格数据有所区别.所以单独赋予了类,可以方便控制.下面我们开始CSS代码的编写:由 www.169it. ...
- 【转】MySQL的安装与配置
一.MySQL的安装 1.在线安装: 命令:sudo apt-get install mysql-server 在安装的过程中将提示为“root”用户设置密码,输入自己的密码即可,安装按成后已自动配置 ...
- linux(ubuntu)和windows下面快速搭建android开发环境
在windows和linux下面搭建android开发环境,一般要安装以下几个软件: 1.JDK安装 2.Eclipse安装 3.Android SDK安装 4.在eclipse里面安装ADT 5.e ...
- 抽象类[abstract]_C#
抽象类(abstract) abstract修饰符可以和类.方法.属性.索引器及事件一起使用.在类声明中使用abstract修饰符以指示某个类只能是其它类的基类.标记为抽象或包含在抽象类中的成员必须通 ...
- [GeekBand] 探讨C++新标准之新语法——C++ 11~14
一. 可变参数模板(Variadic Templates) 在C++11中,出现了参数数目可变的模板,这部分在之前C++高级编程的时候就有学习到. 其实,在C中就有类似的设定.最常用的printf() ...
- 结构型模式——Adapter
1.意图 将一个类的接口转换成客户希望的另一个接口.使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 2.结构 类适配器 对象适配器 3.参与者 Target定义Client使用的与特定领域 ...
- Projected Coordinate Systems
Coordinate Systems Projected Coordinate Systems This is an archive of a previous version of the ArcG ...
- DTCMS获取栏目子类
<%set DataTable categoryList=get_category_child_list(channel,0)%> <%foreach(DataRow cdr in ...
- Android 核心组件 Activity 之下
创建新的Activity的方式: 1. 在相应的文件下 Ctrl + N (Eclipse, Android中不知道是不是) 2. 创建类,继承自Activity或者Activity的子孙类, 并在 ...