Windows下动态链接之三:DLL Hell !

不止Linux下关于共享库存在版本兼容性困扰问题,Windows下DLL共享库的使用问题更甚。很多Windows的应用程序在发布release版本时会一次性将所有用到的DLL一起打包形成一个大的安装包,用户只需一键安装,无需关注具体的DLL文件的配置问题。但也正是这种黑盒操作导致了可能存在某次安装,将系统中的新版本DLL文件被旧版本DLL给覆盖掉,虽然安装的程序可以运行了,但是其他程序可能出现问题了(最为常见的便是Visual studio C++的一些插件库版本覆盖问题)。

前人总结的经验,DLL HELL发生的三种主要场景:
1. 使用旧版本的DLL替代了当前系统的新版本DLL,导致了其他程序无法正常运行;
2. 新版本DLL引入覆盖了旧版本DLL,因为新版本的DLL设计缺陷,没有做到完全的向后兼容;
3. 新版本DLL本身就存在bug,导致程序运行崩溃,很少见。

解决DLL Hell的方法

预防DLL Hell的方法有以下几种:
1.静态链接(static linking):发布终极融合版本执行文件,从根本上杜绝了动态加载DLL的可能性,但也丧失了灵活升级的好处;

2.防止DLL覆盖
在Windows中,DLL的覆盖问题可以使用Windows文件保护(Windows File Protection WFP)技术来缓解。该技术从Windows2000开始使用。它能阻止未经授权的应用程序覆盖系统的DLL。第三方应用程序不能覆盖操作系统DLL文件,除非它们的安装程序捆绑了Windows更新包,或者在它们的安装程序运行时禁止WFP服务(当然这是一个非常危险的事);

3.避免DLL冲突(conflicting DLLs)
解决不同应用程序依赖相同DLL不同版本的问题的一个方案是,让每个应用程序拥有一份自己依赖的DLL,并且把问题DLL的不同版本放到该应用程序的文件夹中,而不是系统DLL目录中,当应用程序需要安装DLL时候,首先从自己的文件夹下寻找所需要的DLL,然后再到系统文件夹中寻找。

4. .NET下DLL Hell的解决方案
在.NET框架中,一个程序集(Assembly)有两种类型:应用程序程序.exe和库程序.dll。一个程序集包括一个或多个文件,所以需要一个清单文件来描述程序集清单,这个清单文件叫做manifest文件。
Manifest文件描述了程序集的名字、版本号、本地文件资源以及程序集依赖的各种资源。Manifest是一个XML描述文件,每个DLL有自己的manifest,每个程序也有自己的manifest。对于应用程序而言,manifest可以和可执行文件在同一个目录下,也可以作为一个资源嵌入到可执行文件的内部(Embed Manifest)。

在XP之后,操作系统在执行可执行文件时会首先读取程序集的manifest文件,获得该可执行文件所需要的DLL列表,再根据具体的DLL名(包括了版本号等信息)去寻找相应的DLL文件。但是这意味Windows得保存一个DLL共享库的所有版本,已提供给系统精准的匹配。(参见\Winodws\WinSxS目录,该目录下有一系列的同名DLL不同版本的保存

对于每个版本DLL,它在WinSxS目录下都有独立的目录,这个目录命令规则要包含机器类型、DLL名字、公钥和版本号,这样多个不同版本的foo.dll就可以存在系统中而不冲突。但是这种方式过于死板,要求DLL版本等信息必须准确对应,所以这也是为什么Windows下的应用程序发布得自己配备所需的DLL的原因,因为很可能主机上没有你要的那个DLL版本。从这里一对比便可以看到,Linux的共享库版本符号机制便是一个好的设计。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值