读书人

彻底崩溃的VS2005 DLL之Singleton模板

发布时间: 2012-10-21 09:00:07 作者: rapoo

彻底崩溃的VS2005 DLL之Singleton模板
class Derived:public TSingleton<Derived>{}

继承自TSingleton<>模板,当new出Derived时,TSingleton<Derived>构造函数向静态变量Derived* s_pInstanceSingleton写入this值.调用TSingleton<>::GetpInstance()能够返回以前写入的this值

问题出在Dll上,使用的是MFC扩展Dll,使用Console调用.测试代码写在Dll01中,TSingleton写在Dll00中.两个Dll中分别定义了一个用于测试的Derived类,分别是CTest02和CTest05,代码几乎一模一样.

类似于
class AFX_EXT_CLASS CTest2:public TSingleton<CTest2>
{
public:
CTest2(void);
virtual ~CTest2(void){}

void SayHello(void)
{
std::cout<<"Hello Test2"<<m_strNameBase<<m_nSeq<<std::endl;
}

void SayHelloMsg(){
AfxMessageBox(_T("Hello Test2"));
}
};
CTest2::CTest2(void):TSingleton(this,"CTest2"){}

Dll01的用例"CTest05"没有问题,异地Dll00的用例 "CTest02"写入后调用GetpInstance返回是Null.后来用GetpInstance2返回了非Null值.但是对象被创建了2次.从Console输出可以看到.
更加诡异的是如果将CTest02的构造函数写在.h文件(class结构内)中,则没有问题.而写在.cpp中,即使加了inline也没有用

template的静态指针型变量 象蒸发了一样.

翻阅了Addison的C++ Templates: The Complete Guide 好像似乎有个章节是CRTP,不过没有深入展开.
安装的是VS2005sp1英文版,不知道是何原因?

MFC Ext Dll00

C/C++ code
//Singleton.h,基础类,检查是否有违规class AFX_EXT_CLASS CSingleton{protected:    static std::set<std::string> s_setStr;public:    CSingleton(const std::string& strName);    virtual ~CSingleton(void){}};//Singleton.cpp,基础类,检查是否有违规std::set<std::string> CSingleton::s_setStr;CSingleton::CSingleton(const std::string& strName){    if(s_setStr.find(strName)!=s_setStr.end()){        std::cout<<"duplicate!"<<std::endl;    }    s_setStr.insert(strName);}//TSingleton.h,模板类template<class Tp>class TSingleton:public CSingleton{protected:    static Tp* s_pInstanceSingleton;    static std::string s_strSingletonName;    std::string m_strNameBase;    static int m_nSeq;protected:    TSingleton(Tp* pThis,const std::string& strT);/*:CSingleton(strT);    {        s_strSingletonName=strT;        s_pInstanceSingleton=pThis;    }*/    virtual ~TSingleton(void)    {        s_pInstanceSingleton=NULL;        std::cout<<"deleted: "<<s_strSingletonName<<std::endl;    }public:    static Tp* GetpInstance()    //with no auto create    {        if(s_pInstanceSingleton){            std::cout<<"GetpInstance() success: "<<s_strSingletonName<<std::endl;            return s_pInstanceSingleton;        }        std::cout<<"fail to load class's instance: "<<s_strSingletonName<<std::endl;        return NULL;    }    static Tp* GetpInstance2()    //with auto create    {        if(s_pInstanceSingleton){            std::cout<<"GetpInstance2() success: "<<s_strSingletonName<<std::endl;            return s_pInstanceSingleton;        }        s_pInstanceSingleton=new Tp;        AfxMessageBox(_T("new instance"));        return s_pInstanceSingleton;    }};template<class Tp> Tp* TSingleton<Tp>::s_pInstanceSingleton;template<class Tp> std::string TSingleton<Tp>::s_strSingletonName="unknown";template<class Tp> int TSingleton<Tp>::m_nSeq=0;template<class Tp>  TSingleton<Tp>::TSingleton(Tp* pThis,const std::string& strT):CSingleton(strT),s_pInstanceSingleton(pThis){    this->s_strSingletonName=strT;    this->s_pInstanceSingleton=pThis;    this->m_strNameBase=strT;    this->m_nSeq++;    std::cout<<m_strNameBase<<" created: "<<m_nSeq<<std::endl;    //s_pInstanceSingleton=dynamic_cast<Tp*>(this);}//测试体02.hclass AFX_EXT_CLASS CTest2:public TSingleton<CTest2>{public:    CTest2(void);    virtual ~CTest2(void){}        void SayHello(void)    {        std::cout<<"Hello Test2"<<m_strNameBase<<m_nSeq<<std::endl;    }        void SayHelloMsg(){        AfxMessageBox(_T("Hello Test2"));    }};//测试体02.cppCTest2::CTest2(void):TSingleton(this,"CTest2"){} 



MFC EXT DLL01
C/C++ code
//测试体05.h#include "stdafx.h"class AFX_EXT_CLASS CTest5:public TSingleton<CTest5>{public:    CTest5(void);    virtual ~CTest5(void);    void SayHello(void);    void SayHelloMsg();};//测试体05.cppCTest5::CTest5(void):TSingleton(this,"CTest5"){}CTest5::~CTest5(void){}void CTest5::SayHello(void){    std::cout<<"Hello Test5"<<std::endl;}void CTest5::SayHelloMsg(){    AfxMessageBox(_T("Hello Test5"));}//测试CTest02,CTest05#include "Test5.h"class AFX_EXT_CLASS CTestAll{public:    CTestAll(void);    virtual ~CTestAll(void);public:    void TestConsole()    {        new CTest2;        CTest2* pTest2=CTest2::GetpInstance();        if(pTest2){            pTest2->SayHello();        }else{            std::cout<<"Call Fail 2"<<std::endl;            pTest2=CTest2::GetpInstance2();            CTest2::GetpInstance()->SayHello();        }                new CTest5;        CTest5* pTest5=CTest5::GetpInstance();        if(pTest5){            pTest5->SayHello();        }else{            std::cout<<"Call Fail 5"<<std::endl;            pTest5=CTest5::GetpInstance2();            CTest5::GetpInstance()->SayHello();        }        delete pTest2;        delete pTest5;    }    void TestGui()    {        new CTest2;        CTest2* pTest2=CTest2::GetpInstance();        if(pTest2){            pTest2->SayHelloMsg();        }else{            AfxMessageBox(_T("Call Fail 2"));            pTest2=CTest2::GetpInstance2();            CTest2::GetpInstance()->SayHello();        }        new CTest5;        CTest5* pTest5=CTest5::GetpInstance();        if(pTest5){            pTest5->SayHelloMsg();        }else{            AfxMessageBox(_T("Call Fail 5"));            pTest5=CTest5::GetpInstance2();            CTest5::GetpInstance()->SayHello();        }        delete pTest2;        delete pTest5;    }};

MFC console Exe文件,Depends on Dll00,Dll01
C/C++ code
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){    int nRetCode = 0;    // initialize MFC and print and error on failure    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))    {        // TODO: change error code to suit your needs        _tprintf(_T("Fatal Error: MFC initialization failed\n"));        nRetCode = 1;    }    else    {        CTestAll test;        test.TestConsole();    }    return nRetCode;}


[解决办法]
珍惜生命,远离扩展dll,只使用纯C接口的标准dll
[解决办法]
这也太长了吧。。。
[解决办法]
在windows下做这种事难度总是很大,毛病很多。

读书人网 >C++

热点推荐