DLL Hell的产生和如何有效的避免

Dll Hell究竟是何物

  • DLL HELL字面意思是DLL"地狱",是由于DLL组件升级引起的程序不能运行的情况。
  • 共享模块常常被编译为Dll文件。Dll共享的方式虽然很不错,但是它自身存在致命的缺陷。由于Dll模块可以被重用,这样多个程序可能使用一个Dll模块 ,如果这个Dll模块升级了,就很有可能出现其中某个程序无法和新的Dll模块很好的兼容起来,导致程序不能运行的情况,这种情况被称为“DLL HELL”。有时安装了新的软件后很多其他的软件都无法使用,往往就是这个原因。
  •  Windows系统是以Dynamic Link Library(动态链接库)的方式让系统和应用软件共用所有的系统文件的。
  •  DLL Hell的意思就是因为系统文件被覆盖而让整个系统像是掉进了地狱(什么软件都不能运行了)。

 

Dll Hell产生的原因是什么

  •  很多windows的应用程序在发布的时候会将它们所有要用到的DLL都一起打包发布,很多应用程序的安装程序都不是很成熟,经常在安装的时候将一个旧版本的DLL覆盖掉一个更新版本的DLL,从而导致其他的应用程序运行失败。有些安装程序比较友好,如果碰到需要覆盖新版的DLL时,它会弹出一个对话框提醒用户是否覆盖,但是即使这样,有些应用程序只能运行在旧版本的DLL下,如果不覆盖,那么它可能无法在新版的DLL中运行。总的来说,有三种可能的原因导致了DLL Hell的发生。 
  •  一是由使用旧版本的DLL替代原来一个新版本的DLL而引起的。这个原因最普遍,是Windows 9X用户通常遇到的DLL错误之一。
  • 二是由新版DLL中的函数无意发生改变而引起。尽管在设计DLL时候应该向下兼容,然而要保证DLL完全向下兼容却是不能的。 
  •  三是由新版DLL的安装引入一个新的Bug

 

 

Dell Hell在编程中是如何产生的

 

面向导出接口\静态类的Dll

  •  接口中某个函数的参数发生改变
  •  接口中某个函数的参数的顺序发生改变
  •  接口中某个函数的参数的类型发生改变
  •  接口中函数的返回值类型发生改变

 

面向导出类的Dll

  • 类大小发送变化(成员变量的增,删,改)
  • 类中虚函数的数目发生改变时(增,删)
  • 类中虚函数的顺序发生改变①
  • 类中某个函数的参数发生改变
  • 类中某个函数的参数的顺序发生改变
  • 类中某个函数的参数的类型发生改变
  • 类中函数的返回值类型发生改变

 

①:在使用Dll导出类指针时容易出现Dll Hell,指针对象的虚函数的寻址方式为编译时确定的,所以直接调用指针对象的虚函数是非安全的。

 

 

 

如何有效的解决Dll Hell的问题

面向导出接口的Dll

  • 不对已输出的函数进行删除和函数的参数的个数,参数顺序,返回值做修改。
  • 允许增加函数和调整函数的顺序。

弊端:当需求增加或修改时可能原有某功能函数无法满足需求,导致修改了原有函数的参数个数,参数类型,参数顺序和返回值类型后导致新旧版本兼容失败(当然也可以新增加一个函数,但是函数可能完成的功能一样但是函数名不一样导致理解困难)

解决方式:采用静态类导出方式,如果需求增加或修改,不动原有的功能函数,只需重载现有函数或增加函数即可(如果某些Dll需要运行时才加载的可采用延时加载Dll技术,工程->配置属性->链接器->输入->延迟加载的Dll)

 

面向导出类的Dll

  • 将类的构造函数和析构函数()设为私有类型(也可用保护类型,可用于外部继承),使外部无法进行对象的构造和析构,避免类的大小发生变化时导致使用的程序产生异常。增加静态函数CreateInstance,DestroyInstance对导出类进行对象的申请和释放。
  • 不对已输出的函数进行删除和函数的参数的个数,参数顺序,参数类型和返回值类型做修改。
  • 允许增加非虚函数和调整非虚函数的顺序。
  • 如果考虑后期的扩展(虚函数的增加),可以再输出类的成员变量中增加一个扩展类指针,在构造函数初始化时对扩展类指针进行定义。
  • 将导出类的成员变量设置为私有方式,防止类在继承时使用了成员变量导致异常(当导出类的成员变量类型或顺序发生变化时产生)
  • 将导出类的析构函数设置为虚析构函数。
  • 将所有虚函数设置为保护类型,不对外输出非虚函数接口,需要输出时采用非数函数调用虚函数接口的形式,即NVI(None Virtual Interface)接口方式,也就是模板方法模式。


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值