简单的单例模式 - Visual C ++断言失败

时间:2012-06-22 09:58:09

标签: visual-c++ singleton c++-cli assert

我最近在Visual C ++ 2010中编写了一个非常简单的logger类,但是我遇到了问题。每次运行程序时,都会出现调试断言失败。

Expression: _CrtIsValidHeapPointer(pUserData)

这就是我班级的样子(基本上只是从这里的答案C++ Singleton design pattern稍微修改一下):

class Logger
{
public:
    // Returns static instance of Logger.
    static Logger& getInstance()
    {
        static Logger logger; // This is where the assertion raises.
        return logger;
    }

    void logError(std::string errorText);

    // Destructor.
    ~Logger();

private:
    std::ofstream logFileStream;

    // The constructor is private to prevent class instantiating.
    Logger();
    // The copy constructor and '=' operator need to be disabled.
    Logger(Logger const&) { };
    Logger& operator=(Logger other) { };
};

构造函数是:

Logger::Logger()
    : logFileStream(Globals::logFileName, std::ios_base::trunc)
{
    // (Tries to open the file specified in Globals for (re)writing.)
}

我发现我可以通过某种方式使用静态变量或方法来解决它,但我不明白这段代码有什么问题。有谁知道,问题在哪里?

编辑:仅供参考,调用此代码时失败(第一次):

Logger::getInstance().logError("hello");

编辑2:这是logFileNameGlobals的定义:

static const std::string logFileName = "errorLog.log";

2 个答案:

答案 0 :(得分:1)

我的猜测是你从另一个全局变量的构造函数中调用getInstance(),并遇到臭名昭着的初始化顺序fiasco - 未指定Globals::logFileName是否已在其他全局变量之前初始化翻译单位。

一个解决方法是使用旧式C字符串,在调用任何全局构造函数之前将对其进行静态初始化:

static const char * logFileName = "errorLog.log";

另一种可能性是通过函数访问它:

static std::string logFileName() {return "errorLog.log";}

我最喜欢的解决方案是完全删除全局实例,并传递对它的任何需求的引用;但是有些人可能会觉得这很乏味,特别是如果你已经拥有大量使用全局的代码。

答案 1 :(得分:0)

C ++ / CLI不是标准的C ++,而是采用略有不同的规则。你在使用C ++ / CLI托管代码吗? (/ clr编译器选项?)当将C ++(非托管)代码与C ++ / CLI(托管)代码混合时,这看起来是一个常见问题。它与程序初始化和程序退出时托管和非托管构造和破坏的方式有关。删除析构函数对我有用 - 你能在Logger类中做到吗?

有关详细信息和可能的解决方法:

http://www.codeproject.com/Articles/442784/Best-gotchas-of-Cplusplus-CLI

http://social.msdn.microsoft.com/Forums/vstudio/en-US/fa0e9340-619a-4b07-a86b-894358d415f6/crtisvalidheappointer-fails-on-globally-created-object-within-a-static-llibrary?forum=vcgeneral

http://forums.codeguru.com/showthread.php?534537-Memory-leaks-when-mixing-managed-amp-native-code&p=2105565