当前位置:首页 » 软件开发
开发技术指南» 文章正文
    引言: 原作者:Ivan S Zapreev 译者:陆其明 概要 本文将要介绍DLL的向后兼容性问题,也就是著名的“DLL Hell”问题。
 

 

    摘要: 首先看一下下面的c程序片断: #include <malloc.h> char *p; p = (char * ) malloc (10); p = (char * ) realloc (p,20); ………………………… 这段程序的意思很简单,只有稍有点c基础的人都可以看懂。函数首先定义了一个字符型的指针p,然后为指针p分配了一个10个字节大......
    摘要: (1)在mfc中更新视图 本文代码下载:http://image.myfaq.com.cn/files/20040514/10344.exe q:我想在我的mdi程序中实现:在cmainframe的一个定时器事件中更新所有的子窗口。我的视图显示很多图表,但我用下面的代码只能更新一个活动窗口: getactivewindow()->getactiveview()->getd......


经典编程:DLL地狱及其解决方案
原作者:ivan s zapreev

  译者:陆其明 【程序编程相关:thinking in c++ 卷2

   【推荐阅读:走进Windows 2000 内部(二)

  概要 【扩展信息:thinkng in c++卷2

  

  

  本文将要介绍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)给一个类增加一个成员变量将导致类尺寸的改变(给原本有虚函数表的类增加一个虚函数将不会改变类的尺寸).假设这个成员增加在类声明的最后.
...   下一页
 ·vb与vc通信初探(一)    »显示摘要«
    摘要:在使用vb调用vc写的dll的时候,可以实现一些vb不能实现或者很难实现的功能,但是,因为vb与vc之间的数据类型并不总是完全对应的,所以,在进行参数传递的时候,就需要进行类型转换了。下面我将通过逐步的推进的方法,来看看如何达到vb与vc之间的通信。      首先,看一个简单的例子。      vc中的程序:      extern "c" _declspec(dllexport) void r......
» 本期热门文章:

©2000-2007 All Rights Reserved. 最佳浏览:1024X768 MSIE