-1

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

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:这是logFileNamein的定义Globals

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

2 回答 2

1

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

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

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

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

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

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

于 2012-06-22T12:07:42.203 回答
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?论坛=vcgeneral

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

于 2014-05-27T21:28:51.570 回答