1、程序结构是主程序与插件(DLL模式)。主程序提供接口让DLL得到主程序某个类实例(用户数据)的指针,并且是只读模式。不允许删除此指针,所以发布给DLL的此类的头文件没有析构函数。如代码所示。
class IUserData { public: virtual CString GetName() = 0; virtual CString GetUserId() = 0; virtual CString GetPrivatePath() = 0; virtual CString GetDepartId() = 0; virtual const CMapStringToString& GetModuleMap() = 0; };
问题是这样的,工程师在写程序过程中,在卸载某一接件dll时把从主框架中得到的用户数据指针给删除了。
a,由于暴露给DLL的接口没有提供析构函数,所以在插件中delete此指针时,不会调用析构函数。在析构函数里加断点,程序不会执行到,给程序排错制造了困难。
b,此实例已经被删除,但内存块未被重新分配前,所有的内容操作不会报错。当程序报错时,断点所示的地方很难联想到是用户数据实例被删除引起的。
c,解决过程是,通过调试观察内存发现,用户数据指针所指的区域在某个插件卸载后变为fe ee fe ee,根据经验,这是被delete的结果,之后就找到问题所在了。
2、主程序与收发线程。启动收发线程时将主程序建立的Session指针传给收发线程。注销后,Session重新建立,delete后重新new。收发线程也是重新建立,但用的Session指针还是原来被删除的指针,导致问题发生。
a,Session指针已经被删除,但内存块未被重新分配给其它指针前,所有的内存操作不会报错。当程序报错时,断点所示的地方很难联想到是指针被删除引起的。
b,通过调试发现,收发线程里Session的指针所指向的地址没变后,知道问题之所在。