(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的向后兼容性测试是非常必要的!
接下去,我将来讨论一个虚函数的问题,以及对应的一个解决方案。
虚函数与继承
首先来看一下如下的虚函数和继承结构:
/**********DLL导出的类 **********/
class EXPORT_DLL_PREFIX VirtFunctClass{
public:
VirtFunctClass(){}
~VirtFunctClass(){}
virtual void DoSmth(){
//this->DoAnything();
// Uncomment of this line after the corresponding method
//will be added to the class declaration
}
//virtual void DoAnything(){}
// Adding of this virtual method will make shift in
// table of virtual methods
};
/**********客户程序,从DLL导出类派生一个新的子类**********/
class VirtFunctClassChild : public VirtFunctClass {
public:
VirtFunctClassChild() : VirtFunctClass (){}
~VirtFunctClassChild(){};
virtual void DoSomething(){}
};
假设上面的两个类,VirtFunctClass在my.dll中实现,而VirtFunctClassChild在客户程序中实现。接下去,我们做一些改变,将如下两个注释行放开:
//virtual void DoAnything(){}
和
//this->DoAnything();
也就是说,DLL导出的类作了改动!现在如果客户程序没有重新编译,那么客户程序中的VirtFunctClassChild将不知道DLL中VirtFunctClass类已经改变了:增加了一个虚函数void DoAnything()。因此,VirtFunctClassChild类的虚函数表仍然包含两个函数的映射:
1. void DoSmth()
2. void DoSomething()
而事实上这已经不对了,正确的虚函数表应该是:
1. void DoSmth()
2. void DoAnything()
3. void DoSomething()
问题就在于,当实例化VirtFunctClassChild之后,如果调用它的void DoSmth()函数,DoSmth()函数转而要调用void DoAnything()函数,但此时基类VirtFunctClass只知道要调用虚函数表中的第二个函数,而VirtFunctClassChild类的虚函数表中的第二个函数仍然是void DoSomething(),于是问题就出来了!
另外,禁止在DLL的导出类的派生类(上例中的VirtFunctClassChild)中增加虚函数也是于事无补的。因为,如果VirtFunctClassChild类中没有virtual void DoSomething()函数,基类中的void DoAnything()函数(虚函数表中的第二个函数)调用将会指向一个空的内存地址(因为VirtFunctClassChild类维持的虚函数表仅仅维持有一个函数地址)。
|
正在阅读:经典编程:DLL地狱及其解决方案经典编程:DLL地狱及其解决方案
2004-05-17 10:05
出处:CSDN
责任编辑:linjixiong
键盘也能翻页,试试“← →”键
相关文章
怎么查看进程正在调用哪些DLL文件
Win7系统取消dll文件关联的方法
win7系统玩游戏提示XINPUT1-3.dll丢失怎么处理
Win7笔记本系统如何添加注册dll和反注册dl
winxp系统开机dLL文件出错提示的具体处理步骤
360se.exe应用程序出错 计算机中丢失demaxiya.dll解决方法
pgort100.dll丢失 QQ提示pgort100.dll报错解决方法
msvcr100.dll丢失 QQ提示msvcr100.dll报错解决方法
win7 64位系统无法运行程序提示找不到tbb_debug.dll
win7旗舰版64位系统开机提示找不到comctl32.dll