C++ 单例模板类使我的程序崩溃

Posted

技术标签:

【中文标题】C++ 单例模板类使我的程序崩溃【英文标题】:C++ singleton template class crashes my program 【发布时间】:2019-11-27 04:32:29 【问题描述】:

我创建了一个单例模式作为模板类。

template <typename T>
class TemplateSingleton

protected:
    TemplateSingleton()  
    virtual ~TemplateSingleton()  

public:
    static T * GetInstance()
    
        if (m_pInstance == NULL) 
            m_pInstance = new T;

        return m_pInstance;
    ;

    static void FreeInstance()
    
        if (m_pInstance != NULL)
        
            delete m_pInstance;
            m_pInstance = NULL;
        
    ;

private:
    static T * m_pInstance;
;

template <typename T> T * TemplateSingleton<T>::m_pInstance = NULL;

并使用继承自子类。 这个类可以通过继承模板作为单例类使用,如果不继承,也可以作为泛型类使用。

#define MAX_COUNT 8

class CDataHandler : public TemplateSingleton<CDataHandler>

public:
    CDataHandler();
    ~CDataHandler();
    ...

private:
    CDataObj m_clDataObj[MAX_COUNT]; // CDataObj *m_clDataObj ?
    DWORD m_dwDataObjCount;
    ...
;

class CDataObj

public:
    CDataObj();
    ~CDataObj();
    ...

private:
    ...
;

上面的代码是在一个DLL中,程序被实现为只调用CDataHandler的实例构造函数。 我的程序崩溃并退出。

顺便说一句,如果我将 CDataObj 成员变量从数组更改为指针,它工作正常。 (本例在CDataHandler的构造函数中新建,在析构函数中删除。)

这段代码有问题吗?

加法) CDataHandler 的构造函数和析构函数代码:)

CDataHandler::CDataHandler()
    : m_dwDataObjCount(0)
    //, m_clDataObj(NULL)

    // Do nothing

    // m_clDataObj = new CDataObj[MAX_COUNT]; 

CDataHandler::~CDataHandler()

    //if (m_clDataObj != NULL)
    
        for (int i = 0; i < MAX_COUNT; i++)
        
            m_clDataObj[i].Close();
        

        // delete[] m_clDataObj; 
        // m_clDataObj = NULL;
    

【问题讨论】:

你是如何实现 CDataHandler ctor 和 dtors 的? 崩溃的原因在于您决定不向我们展示的代码。 @Arun 添加了 CDataHandler 的构造函数和析构函数源代码 @SidS 上面的代码有语法错误吗?如果是这样,应该在其他地方考虑这个问题...... 【参考方案1】:

不确定是什么导致您的程序崩溃,但您发布的代码中存在两个潜在问题。

首先,您不知道m_pInstance 何时会被初始化为NULL。如果在静态数据初始化期间调用GetInstance()m_pInstance 可能尚未初始化为NULL,因此GetInstance() 将返回一些无效指针。查找“静态数据初始化命令fiasko”之类的,这方面的信息很多。

为避免这种情况,您可以使用局部静态变量,如下所示:

T* GetInstance()

  static T* t = new T;
  return t;

其次,您为单身人士使用模板。没关系,但您必须注意:如果类的定义可用于多个编译单元,则这些编译单元中的每一个都将实例化它们自己的单例,根据您来自哪个编译单元,为您留下多个不同的实例访问它们。

为了解决这个问题,您可以在 DLL 中使用 extern template 为某个 T 告诉其他人他们不应该实例化此模板特化,然后将显式模板实例化编译到 DLL 中,以便为每个人提供实现。

【讨论】:

感谢您的回答。经过几天的调试,似乎不是模板单例。发现容错堆(FTH)相关的日志写入DebugView,在初始化FTH列表的时候就可以了。

以上是关于C++ 单例模板类使我的程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

我想从 C++ 非托管代码调用 C# 委托。无参数委托工作正常,但有参数委托使我的程序崩溃

为啥 ntdll.dll 会使我的 c++ 可执行文件崩溃?

为啥我的班级用错误代码 138 使我的 OCUnit 测试用例崩溃?

c ++我在Windows操作系统上获取文件创建日期的方法使我的控制台应用程序崩溃

如何使我的应用程序单例应用程序? [复制]

为啥我的 ListView 使我的应用程序崩溃而不是列出我的条目?