DLL“ 地狱 ”的原因及其解决方案
- 格式:pdf
- 大小:312.30 KB
- 文档页数:9
XP开机时提示“DLL文件出错”的处理方法一、需求背景我部在日常维护中经常遇到XP启动故障,用户开机时,系统提示“拒绝访问。
加载某某文件出错。
最近在一次服务中,就遇到了一次,系统报”加载C:/WINDOWS/SYSTEM32/UKSEG06.DLL出错”。
二、问题分析通过现象,我们分析判断认为:这可能是某应用程序被非正常删除所致。
随着软件的逐步成熟,各类软件为追求强大的功能和良好的使用效果,在安装时会对系统注册表进行一些改动,假如直接删除应用软件的安装目录,但其相关的注册信息却还在,导致系统开机时还加载它,却又找不到它的文件,所以报错。
我们知道大部分软件都提供了卸载程序,卸载时点击其“程序”菜单中的“卸载某某”即可。
如果找不到,可在“开始→设置→控制面板→添加/删除程序→安装/卸载”标签中的列表内找到要卸载的程序(如果有的话),按“添加/删除”按钮即可,而绿色软件不在注册表中植入任何信息,不对系统文件进行任何修改,所有文件只存在于一文件夹中,删除它只需将整个文件夹删除。
针对这个问题的处理就是找到应用程序残留的设置,然后删除。
三、解决方案办法一:开始——运行——msconfig——启动——把加载UKSEG06.dll的软件禁用。
办法二:开始——运行——regedit,在下面的位置找到并删除相应键值:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ RunHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion \Run办法三:使用专用工具清理注册表,最好用Regcleaner这个专用软件扫描并删除。
四、创新启示:目前各类应用软件十分丰富,删除自己不用的程序也需要规范,不然遗留的尾巴会影响你计算机的运行。
DLL“地狱”的原因及其解决方案概要本文将要介绍DLL的向后兼容性问题,也就是著名的“DLL Hell”问题。
首先我会列出自己的研究结果,其中包括其它一些研究者的成果。
在本文的最后,我还将给出“DLL Hell”问题的一个解决方案。
介绍我曾经接受过一个任务,去解决一个DLL版本更新的问题————某个公司给用户提供了一套SDK,这个SDK是由一系列DLL组成的;DLL中导出了很多类,用户使用这些类(直接使用或派生新的子类)来继续他们的C++ 程序开发。
用户在使用这些DLL时没有得到很详细的使用说明(比如使用这些DLL中导出的类有什么限制等)。
当这些DLL更新为新的版本之后,他们发现他们开发的基于这些DLL的应用程序会经常崩溃(他们的应用程序从SDK 的导出类派生了新的子类)。
为了解决这个问题,用户必须重新编译他们的应用程序,重新连接新版本的SDK DLL。
我将对这个问题给出我的研究结果,同时还有我从其它地方搜集过来的相关信息。
最后,我将来解决这个“DLL Hell”问题。
研究结果就我个人的理解,这个问题是由SDK DLL中导出的基类改动之后引起的。
我查看了一些文章后发现,DLL的向后兼容性问题其实早有人提出。
但作为一个实在的研究者,我决定自己做一些试验。
结果,我发现如下的问题:1. 在DLL的导出类中增加一个新的虚函数将导致如下问题:(1)如果这个类以前就有一个虚函数B,此时在它之前增加一个新的虚函数A。
这样,我们改变了类的虚函数表。
于是,表中的第一个函数指向了函数A(而不是原来的B)。
此时,客户程序(假设没有在拿到新版本的DLL之后重新编译、连接)调用函数B就会产生异常。
因为此时调用函数B实际上转向了调用函数A,而如果函数A和函数B的参数类型、返回值类型迥异的话问题就出来了!(2)如果这个类原本没有虚函数(它的父类也没有虚函数),那么给这个类增加一个新的虚函数(或者在它的父类增加一个虚函数)将导致新增加一个类成员,这个成员是一个指针类型的,指向虚函数表。
DLL文件基本原理及修改方法DLL文件基本原理及修改方法和通过改DLL来美化系统图标一、DLL文件常识DLL是Dynamic link Library的缩写,意为动态链接库。
在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。
当我们执行某一个程序时,相应的DLL文件就会被调用。
一个应用程序可有多个DLL文件,一个DLL 文件也可能被几个应用程序所共用,这样的DLL文件被称为共享DLL文件。
DLL文件一般被存放在C:WindowsSystem目录下二、修改DLL文件的具体应用在系统的组策略和注册表中,我们可以修改一些键值来优化我们的系统,并加强操作系统的安全性。
可是,对于限制下载、禁止删除文件等功能,我们无法通过上述的操作来完成,这只有通过修改系统DLL文件来实现。
目前,我们通过修改系统的DLL文件,可以实现禁止删除文件、禁止IE下载、禁止IE另存为、禁止文件打开方式等功能。
三、系统中部分DLL文件的功能1、Browselc.dll IE所需要调用的库文件DLL结构雏形就是它了2、Shdoclc.dll 系统窗口及设置等,如删除文件、重命名3、Shell32.dll 系统窗口及设置等,如删除文件、重命名4、Cryptui.dll IE控件下载及提示对话框程序四、修改DLL文件的方法1、下载DLL文件修改工具EXESCOPE6.0-6.3或6.4工具2、获取Browselc.dll、Shdoclc.dll、Shell32.dll和Cryptui.dll这几个链接文件。
在找这几个文件时,最好将其他机器的硬盘,挂接在本机中,然后用本机的操作系统启动并复制这几个文件。
3、在修改DLL文件的时候,打开该键值,在右面的对话框中将所要修改的键值禁用即可,不要删除,以备日后恢复(如图)五、DLL文件修改秘籍1、禁止下载的修改方法:打开Shdoclc.dll修改资源--对话框---4416,将4416键值禁用即可。
加载DLL文件失败的解决办法开机提示找不到 *.dll 解决小结。
最近这个问题很多,把这个也总结一下吧,欢迎大家提出其它意见供大家参考:首先查一下是哪个.dll无法加载,试着手动regsvr32 *.dll加载试试1、开始-运行,输入msconfig,在“启动”中把相关自启动的选项都去掉。
2、关闭系统还原。
(我的电脑-属性-系统还原,选择“在所有的驱动器上关闭系统还原”)3、把C:\Documents and Settings\用户名\Local Settings\Temp和C:\Documents and Settings\用户名\Local Settings\Temporary Internet Files文件夹下的所有文件都删除。
(如果看不到此文件夹,工具-文件夹选项,在“查看”中有一项是“隐藏文件和文件夹”,选择“显示所有文件和文件夹”)4、把C:\WINDOWS\Prefetch文件夹下的所有文件都删除。
5、控制面板-服务,把你认为不需要的服务都改为“手动”并停用。
6、关闭各种视觉效果(我的电脑-属性,弹出的窗口里选择“高级”标签,性能的设置,选择最佳性能,或者只保留倒数第二项、倒数第三项和在窗口和按钮上保持视觉样式。
)7、关闭远程协助(我的电脑-属性,弹出的窗口里选择“远程”标签,然后取消下面两个选项的选择。
)8、安装优化软件(二者选一即可) TuneUp Utilities 或者Windows 优化大师或者其它的......可能是这个dll因为某些原因(最大的可能是因为它是个病毒或流氓软件的dll 文件,被杀软删除了)丢失了,但其相关的注册信息却还在,导致系统开机时还加载它,却又找不到它的文件,所以报错。
如果你点击“确定”后,系统没有什么不正常,并且可以正常运行的话,你可以用这个软件清理掉这个开机加载项,以后开机就不会出现这个信息了。
Autoruns:开机启动项管理DLL文件即动态链接库文件,是一种可执行文件,它允许程序共享执行特殊任务所必需的代码和其他资源。
dll注入应急案例近年来,随着网络攻击手法的不断更新和演进,DLL注入攻击作为一种有效的攻击技术不断被黑客和恶意分子滥用。
本文将通过一则DLL注入应急案例,探讨该攻击技术的特点、危害性以及应对措施,以提高读者对这一威胁的认识和应对能力。
案例描述某公司近期发现其内部计算机系统出现异常情况,怀疑系统被黑客入侵并进行恶意活动。
经过调查,安全团队发现系统中的某个进程被恶意DLL注入修改,从而导致黑客可以远程操控该进程,并获取系统权限。
DLL注入攻击原理DLL注入攻击是指黑客将恶意动态链接库(DLL)注入到目标进程的内存空间中,以获取目标进程的控制权,从而进行恶意行为。
攻击者通常通过以下几种方式进行DLL注入:1. 远程线程注入:攻击者通过远程线程注入的方式,将恶意DLL 注入到目标进程所在的远程线程中,实现攻击目的。
2. 进程空间注入:攻击者通过进程空间注入的方式,将恶意DLL 注入到目标进程的内存空间中,绕过系统的安全机制。
3. 代码注入:攻击者通过修改目标进程的代码,将DLL加载并执行,实现攻击目的。
DLL注入攻击的危害性DLL注入攻击具有以下危害性:1. 获取系统权限:通过DLL注入攻击,黑客可以获取目标进程的控制权,进而获取系统权限,导致系统完全被黑客控制。
2. 数据泄露:黑客可以利用DLL注入攻击,获取系统中的敏感信息,如用户账号、密码等,进而进行个人信息泄露、商业机密窃取等违法行为。
3. 恶意启动:黑客可以利用DLL注入攻击,在目标进程中启动恶意代码,如勒索软件、恶意挖矿程序等,进一步损害系统正常运行。
应对措施针对DLL注入攻击,我们可以采取以下措施进行应对:1. 加强系统安全性:及时安装系统补丁,强化系统防火墙和安全策略,减少系统漏洞。
2. 使用可信的安全软件:选择正规的安全软件,如防病毒软件、入侵检测系统等,并及时更新和升级。
3. 强化访问控制:限制用户权限,合理划分角色,及时删除不必要的用户账号,防止恶意用户进行攻击。
加载dll文件失败,系统找不到指定模块解决方法(2012-11-01 22:23:06)转载▼标签:杂谈前些天,电脑中了病毒,病毒删除后,留了点后遗症,困惑了好几天,问题终于解决了。
方法如下(网上资源转摘)以备后用:这是因为开机自启动的应用程序找不到要调用的DLL文件给出的错误提示。
我们所要做的是判断这个DLL文件是正常应用程序的还是病毒的。
(通常病毒的成份会比较多。
这里我把3721,新浪的那些个鬼玩意儿也归为病毒)如果是正常应用程序的话。
如果可以找到这个DLL文件的话。
那么在运行里输入cmd回车调出命令提示符。
然后把目录转自应用程序的安装目录下。
运行regsvr32 xxxx.dll(就是不能正常加载的那个DLL文件)重新注册一次就可以了。
如果找不到的话。
那你就重新安装这个应用程序吧。
病毒这种情况见得比较多。
最有可能的就是病毒文件本身已经被杀毒软件查杀并删除了。
可启动信息还残留在电脑里。
也就是说。
在开机的时候系统还是会自动搜寻这个文件并试图运行他。
如果找不到的话就会给出类似的提示(所以这里可以举一反三。
并不只是DLL文件。
EXE文件等也是这个原因)这样的话。
你可以在开机启动项里找一找他。
1.电脑加载出错找不到指定的模块若是C:/WINDOWS/bownlo~/cnsMin.dll楼主点开始--运行--regedit--查找--cnsMin.dll--F3--删除--重启即可.]2.如果电脑开机出现'加载c:\progra`1\tencent\ssplus\update\temp2.dat时出错找不到指定的模块这个是QQ的问题,你把QQ御了再重装下,或者将启动时默认启动QQ的那个删掉,在开始,程序,启动栏里,如果没有,你可以尝试下卸掉QQ,重新安装看看]3.出现---加载"c:\**\****.dll"文件时出错,找不到指定模块的解决办法我的许多朋友的机子经常出现开机加载问题,他们被这个问题搞的很烦,久病成医,..下面介绍一下心得:【分析】电脑病毒、木马、流氓软件没杀干净,注册表残留了无用的DLL文件。
.dll是什么文件?该如何修复缺失的DLL文件?时间: 2011-03-14 / 分类: 系统故障解决 / 浏览次数: 1次/ 0个评论发表评论大家在应用软件或者玩游戏的时候,经常会遇到类似提示“找不到xx.dll”或“xx.dll文件缺失”的问题,可见.dll文件应用程序中非常重要的部分,那么.dll是什么文件?该如何预防和.dll 文件缺失或错误的问题呢?.dll是什么文件?Dll文件的全称是Dynamic Link Library,中文意思为动态链接库,DLL文件是不可执行文件,其是一个包含由多个程序同时使用的代码和数据的库,动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数,而函数的可执行代码就位于DLL文件中,Dll文件还有助于共享数据和资源,多个应用程序可以同时访问内存中某个DLL副本的数据!DLL文件缺失损坏的后果:由以上dll文件的介绍可以看出,dll文件在系统和软件中的重要作用,如果有Dll文件缺失或被修改可能造成如下后果:1,不能正常运行某些应用程序,如游戏2,系统不能正常运行,出现电脑蓝屏现象3,系统的某些功能不能正常使用,如没有声音4,桌面某些程序无法删除也是由于DLL文件在后台运行造成的做到以下几点基本可以预防DLL文件产生问题:1,安装官方原版系统,一些阉割版的系统由于精简优化的不合理,很多系统重要组件被阉割掉,经常出现此类dll文件缺失的问题!官方原版系统下载:XP | Windows7 | 更多系统 | 电脑知识2,安装官方原版的软件,很多如绿色版,精简版,破解版的软件已经改变了程序原有的结构,很多重要的组件被去除难以避免!经常玩破解版游戏的朋友应深有体会!3,做好电脑安全防护,避免计算机感染病毒木马删除和修改DLL文件!推荐阅读:1,什么是特洛伊木马?如何主动预防、监控并停止木马的入侵?2,安全的网上冲浪:细数网络安全威胁来源DLL文件缺失该如何修复?DLL文件缺失是一个常见的问题,一般只需要将缺失的DLL文件补回即可解决,推荐一个DLL文件下载地址:雨林木风DLL文件下载站(点击此处进入),进入可手动下载缺失的dll文件!下载后,直接复制到原目录即可解决DLL文件缺失问题!。
电脑提示缺少dll文件怎么办缺少dll文件修复方法
我们经常会遇到在安装或打开某些软件时,电脑系统弹出无法运行,缺少某些dll文件的问题。
如果遇到这种情况就无法继续安装或者运行软件,必须要进行系统修复,才能正常使用。
所以小编在本文中教大家如何修复缺少dll文件的问题。
windows7系列软件最新版本下载
方法一:
1、根据弹出的提示,搜索具体缺少的dll文件,并下载到本地电脑;
2、将其保存到系统盘相应位置,一般位于System32文件夹中;
方法二、
1、从网上下载DirectX修复工具(DirectX Repair);
2、双击打开DirectX修复工具;
3、然后点击“检测并修复”;
4、修复完成后点击确定即可。
以上就是解决电脑缺少dll文件无法运行软件的方法。
DLL 陷阱是一个恶梦,是一种相当奇怪的问题。
相信很多读者都有这样的经验,如果你的软体今天原本运作顺畅,当你安装某个新软体之后,突然间电脑就无法运作了。
这绝对不是你的硬体有问题,也不是应用程序的问题,而是作业系统设计上的缺失,这样的问题层出不穷,这通常是因为新的应用程序版本覆盖掉共享的程序库(DLL),而且往往修改了一些现存应用程序所必需的「bug」,这个缺失有了一个名字叫做DLL Hell (DLL地狱)。
开发人员与系统管理者(以及使用者)面临最大的挑战就是版本更新的问题,他们花很多时间在Windows 登录档(Regedit) 上试着解决其问题而吃尽苦头。
.在Microsoft .NET的世界里,软体元件再也不需要登录(Registry)了!NET Framework包含了一些功能,可以实际消除「DLL Hell」的问题,一项称之为「side-by-side」开发模式的新功能。
DLL & DLL Hell为什么要使用DLL (Dynamic Linking Library) - 动态链接库?微软当初为Windows设计动态链接库主要是撷取它的两项优点:一是动态连结、一是资源共享。
资源共享的例子相当显而易见,例如之前曾经提过Windows有三个核心的动态链接库:Kernel主要是负责系统和应用程序的记忆体、行程和执行绪等等的管理工作;User主要负责使用者介面和讯息的传递;GDI则负责系统的任何图形绘制、显示等工作。
而这些动态链接库所提供的任何函数都可以在必要的时候,让每一个Windows环境底下的执行档使用。
因为DLL 具备节省记忆体的特性,因此自从Windows 3.1版以来,它就逐渐成为Windows程序设计的主流˙动态链接库可以资源共享许多大型软体厂商的众多软体产品可能都会有许多可以共用的模组,如果每一套软体各自拥有一份这些可以共用的模组,不仅会造成磁碟空间的浪费,还会让维护这些模组的工作变的既复杂、又凌乱。
开机提示找不到 *.dll 解决小结。
最近这个问题很多,把这个也总结一下吧,欢迎大家提出其它意见供大家参考:首先查一下是哪个.dll无法加载,试着手动regsvr32 *.dll加载试试1、开始-运行,输入msconfig,在“启动”中把相关自启动的选项都去掉。
2、关闭系统还原。
(我的电脑-属性-系统还原,选择“在所有的驱动器上关闭系统还原”)3、把C:\Documents and Settings\用户名\Local Settings\Temp和C:\Documents and Settings\用户名\Local Settings\Temporary Internet Files文件夹下的所有文件都删除。
(如果看不到此文件夹,工具-文件夹选项,在“查看”中有一项是“隐藏文件和文件夹”,选择“显示所有文件和文件夹”)4、把C:\WINDOWS\Prefetch文件夹下的所有文件都删除。
5、控制面板-服务,把你认为不需要的服务都改为“手动”并停用。
6、关闭各种视觉效果(我的电脑-属性,弹出的窗口里选择“高级”标签,性能的设置,选择最佳性能,或者只保留倒数第二项、倒数第三项和在窗口和按钮上保持视觉样式。
)7、关闭远程协助(我的电脑-属性,弹出的窗口里选择“远程”标签,然后取消下面两个选项的选择。
)8、安装优化软件(二者选一即可) TuneUp Utilities 或者 Windows 优化大师或者其它的......可能是这个dll因为某些原因(最大的可能是因为它是个病毒或流氓软件的dll 文件,被杀软删除了)丢失了,但其相关的注册信息却还在,导致系统开机时还加载它,却又找不到它的文件,所以报错。
如果你点击“确定”后,系统没有什么不正常,并且可以正常运行的话,你可以用这个软件清理掉这个开机加载项,以后开机就不会出现这个信息了。
Autoruns:开机启动项管理DLL文件即动态链接库文件,是一种可执行文件,它允许程序共享执行特殊任务所必需的代码和其他资源。
DLL“地狱”的原因及其解决方案概要本文将要介绍DLL的向后兼容性问题,也就是著名的“DLL Hell”问题。
首先我会列出自己的研究结果,其中包括其它一些研究者的成果。
在本文的最后,我还将给出“DLL Hell”问题的一个解决方案。
介绍我曾经接受过一个任务,去解决一个DLL版本更新的问题————某个公司给用户提供了一套SDK,这个SDK是由一系列DLL组成的;DLL中导出了很多类,用户使用这些类(直接使用或派生新的子类)来继续他们的C++ 程序开发。
用户在使用这些DLL时没有得到很详细的使用说明(比如使用这些DLL中导出的类有什么限制等)。
当这些DLL更新为新的版本之后,他们发现他们开发的基于这些DLL的应用程序会经常崩溃(他们的应用程序从SDK 的导出类派生了新的子类)。
为了解决这个问题,用户必须重新编译他们的应用程序,重新连接新版本的SDK DLL。
我将对这个问题给出我的研究结果,同时还有我从其它地方搜集过来的相关信息。
最后,我将来解决这个“DLL Hell”问题。
研究结果就我个人的理解,这个问题是由SDK DLL中导出的基类改动之后引起的。
我查看了一些文章后发现,DLL的向后兼容性问题其实早有人提出。
但作为一个实在的研究者,我决定自己做一些试验。
结果,我发现如下的问题:1. 在DLL的导出类中增加一个新的虚函数将导致如下问题:(1)如果这个类以前就有一个虚函数B,此时在它之前增加一个新的虚函数A。
这样,我们改变了类的虚函数表。
于是,表中的第一个函数指向了函数A(而不是原来的B)。
此时,客户程序(假设没有在拿到新版本的DLL之后重新编译、连接)调用函数B就会产生异常。
因为此时调用函数B实际上转向了调用函数A,而如果函数A和函数B的参数类型、返回值类型迥异的话问题就出来了!(2)如果这个类原本没有虚函数(它的父类也没有虚函数),那么给这个类增加一个新的虚函数(或者在它的父类增加一个虚函数)将导致新增加一个类成员,这个成员是一个指针类型的,指向虚函数表。
于是,这个类的尺寸将会被改变(因为增加了一个成员变量)。
这种情况下,客户程序如果创建了这个类的实例,并且需要直接或间接修改类成员的值的时候就会有问题了。
因为虚函数表的指针是作为类的第一个成员加入的,也就是说,原本这个类定义的成员因为虚函数表指针的加入而都产生了地址的偏移。
客户程序对原成员的操作自然就出现异常了。
(3)如果这个类原本就有虚函数(或者只要它的父类有虚函数),而且这个类被导出了,被客户程序当作父类来用。
那么,我们不要给这个类增加虚函数!不仅在类声明的开头不能加,即使在末尾处也不能加。
因为加入虚函数会导致虚函数表内的函数映射产生偏移;即使你将虚函数加在类声明的末尾,这个类的派生类的虚函数表也会因此产生偏移。
2. 在DLL的导出类中增加一个新的成员变量将导致如下问题:(1)给一个类增加一个成员变量将导致类尺寸的改变(给原本有虚函数表的类增加一个虚函数将不会改变类的尺寸)。
假设这个成员增加在类声明的最后。
如果客户程序为创建这个类的实例少分配了内存,那么可能在访问这个成员时导致内存越界。
(2)如果在原有的类成员中间增加一个新的成员,情况会更糟糕。
因为这样会导致原有类成员的地址产生偏移。
客户程序操作的是一个错误的地址表,对于新成员后面的成员尤其是这样(它们都因为新成员的加入而导致了自己在类中的偏移的变化)。
(注:上述的客户程序就是指使用SDK DLL的应用程序。
)除了上面这些原因外,还有其它操作会导致DLL的向后兼容性问题。
下面列出了解决(大部分)这些问题的方法。
DLL编码约定简述下面是我搜集到的所有的解决方案,其中一些是从网上的文章中拿来的,一些是跟不同的开发者交流后得到的。
下面的约定主要针对DLL开发,而且是为解决DLL的向后兼容性问题:1. 编码约定:(1)DLL的每个导出类(或者它的父类)至少包含一个虚函数。
这样,这个类就会始终保存一个指向虚函数表的指针成员。
这么做可以方便后来新的虚函数的加入。
(2)如果你要给一个类增加一个虚函数,那么将它加在所有其它虚函数的后面。
这样就不会改变虚函数表中原有函数的地址映射顺序。
(3)如果你打算以后给一个类扩充类成员,那么现在预留一个指向一个数据结构的指针。
这样的话,增加一个成员直接在这个数据结构中修改,而不是在类中修改。
于是,新成员的加入不会导致类尺寸的改变。
当然,为了访问新成员,需要给这个类定义几个操作函数。
这种情况下,DLL必须是被客户程序隐式(implicitly)连接的。
(4)为了解决前一点的问题,也可以给所有的导出类设计一个纯接口的类,但此时,客户程序将无法从这些导出类继续派生,DLL导出类的层次机构也将无法维持。
(5)发布两个版本的DLL和LIB文件(Debug版本和Release版本)。
因为如果只发布Release版本,开发者将无法调试他们的程序,因为Release 版与Debug版使用了不同的堆(Heap)管理器,因而当Debug版本的客户程序释放Release版本DLL申请的内存时,会导致运行时错误(Runtime failure)。
有一种办法可以解决这个问题,就是DLL同时提供申请和释放内存的函数供客户程序调用;DLL中也保证不释放客户程序申请的内容。
通常遵守这个约定不是那么简单!(6)在编译的时候,不要改变DLL导出类函数的默认参数,如果这些参数将被传递到客户程序的话。
(7)注意内联(inline)函数的更改。
(8)检查所有的枚举没有默认的元素值。
因为当增加/删除一个新的枚举成员,你可能移动旧枚举成员的值。
这就是为什么每一个成员应该拥有一个唯一标识值。
如果枚举可以被扩展,也应该对其进行文档说明。
这样,客户程序开发者就会引起注意。
(9)不要改变DLL提供的头文件中定义的宏。
2. 对DLL进行版本控制:如果主要的DLL发生了改变,最好同时将DLL文件的名字也改掉,就象微软的MFC DLL一样。
例如,DLL文件可以按照如下格式命名:Dll_name_xx.dll,其中xx就是DLL的版本号。
有时候DLL中做了很大的改动,使得向后兼容性问题无法解决。
此时应该生成一个全新的DLL。
将这个新DLL安装到系统时,旧的DLL仍然保留。
于是,旧的客户程序仍然能够使用旧的DLL,而新的客户程序(使用新DLL编译、连接)可以使用新的DLL,两者互不干涉。
3. DLL的向后兼容性测试:还有很多很多中可能会破坏DLL的向后兼容性,因此实施DLL的向后兼容性测试是非常必要的!接下去,我将来讨论一个虚函数的问题,以及对应的一个解决方案。
虚函数与继承首先来看一下如下的虚函数和继承结构:假设上面的两个类,VirtFunctClass在my.dll中实现,而VirtFunctClassChild在客户程序中实现。
接下去,我们做一些改变,将如下两个注释行放开:和也就是说,DLL导出的类作了改动!现在如果客户程序没有重新编译,那么客户程序中的VirtFunctClassChild将不知道DLL中VirtFunctClass类已经改变了:增加了一个虚函数void DoAnything()。
因此,VirtFunctClassChild类的虚函数表仍然包含两个函数的映射:1. void DoSmth()2. void DoSomething()而事实上这已经不对了,正确的虚函数表应该是:1. void DoSmth()2. void DoAnything()3. void DoSomething()问题就在于,当实例化VirtFunctClassChild之后,如果调用它的voidDoSmth()函数,DoSmth()函数转而要调用void DoAnything()函数,但此时基类VirtFunctClass只知道要调用虚函数表中的第二个函数,而VirtFunctClassChild 类的虚函数表中的第二个函数仍然是void DoSomething(),于是问题就出来了!另外,禁止在DLL的导出类的派生类(上例中的VirtFunctClassChild)中增加虚函数也是于事无补的。
因为,如果VirtFunctClassChild类中没有virtual void DoSomething()函数,基类中的void DoAnything()函数(虚函数表中的第二个函数)调用将会指向一个空的内存地址(因为VirtFunctClassChild类维持的虚函数表仅仅维持有一个函数地址)。
现在可以看出,在DLL的导出类中增加虚函数是一个多么严重的问题!不过,如果虚函数是用来处理回调事件的,我们有办法来解决这个问题。
COM及其它现在可以看出,DLL的向后兼容性问题是一个很出名的问题。
解决这些问题,不仅可以借助于一些约定,而且可以通过其它一些先进的技术,比如COM技术。
因此,如果你想摆脱“DLL Hell”问题,请使用COM技术或者其它一些合适的技术。
让我们回到我接受的那个任务(我在本文开头的地方讲到的那个任务)————解决一个使用DLL的产品的向后兼容性问题。
我对COM有些了解,因此我的第一个建议是使用COM技术来克服那个项目中的所有问题。
但这个建议因为如下原因最终被否决了:1. 那个产品已经在某个内部层中有一个COM服务器。
2. 将一大堆接口类重写到COM的形式,投入比较大。
3. 因为那个产品是DLL库,而且已经有很多应用程序在使用它了。
因此,他们不想强制他们的客户重写他们的应用程序。
换句话说,我被要求完成的任务是,以最小的代价来解决这个DLL向后兼容性问题。
当然,我应该指出,这个项目最主要的问题在于增加新的成员和接口类上的虚回调函数。
第一个问题可以简单地通过在类声明中增加一个指向一个数据结构的指针来解决(这样可以任意增加新的成员)。
这种方法我在上面已经提到过。
但是第二个问题,虚回调函数的问题是新提出的。
因此,我提出了下面的最小代价、最有效的解决方法。
虚回调函数与继承然我们想象一下,我们有一个DLL,它导出了几个类;客户应用程序会从这些导出类派生新的类,以实现虚函数来处理回调事件。
我们想在DLL中做一个很小的改动。
这个改动允许我们将来可以给导出类“无痛地”增加新的虚回调函数。
同时,我们也不想影响使用当前版本DLL的应用程序。
我们期望的就是,这些应用程序只有在不得已的时候才协同新版本的DLL进行一次重新编译。
因此,我给出了下面的解决方案:我们可以保留DLL导出类中的每个虚回调函数。
我们只需记住,在任何一个类定义中增加一个新的虚函数,如果应用程序不协同新版本的DLL重新编译,将导致严重的问题。
我们所做的,就是想要避免这个问题。
这里我们可以一个“监听”机制。
如果在DLL导出类中定义并导出的虚函数被用作处理回调,我们可以将这些虚函数转移到独立的接口中去。