c++ - 单例的段错误

标签 c++ crash singleton

//非单例 MyLogManager 类 { void write(message) {Ogre::LogManager::getSingletonPtr()->logMessage(message);}

class Utils : public singleton<Utils>
{
   MyLogManager *handle;
   MyLogManager& getHandle { return *handle; }
};

namespace someNamespace
{
   MyLogManager &Log() { return Utils::get_mutable_instance().getHandle(); }
}

int main()
{
   someNamespace::Log().write("Starting game initializating...");
}

在这段代码中,我使用了 boost 的单例(来自序列化)并调用了 Ogre 的日志管理器(它也是单例类型)。

程序在尝试用代码对Ogre::LogManager::getSingletonPtr()对象做一些事情时失败

用户程序被信号 (SIGSEGV) 停止

我检查过 getSingletonPtr() 返回地址 0x000

但是使用代码 Utils::get_mutable_instance().getHandle().write("foo") 在程序的另一部分工作得很好。调用单例可能有什么问题?


Utils 类的真实版本:

class Utils : public singleton<Utils>
{
    protected:
        ConfigManager *configHandlePtr;
        LogManager *logHandlePtr;

    public:
        Utils()
        {
            configHandlePtr = new ConfigManager();

            string engineLog = configHandle().getValue<string>("engine.logFilename", "Engine.log");
            logHandlePtr = new LogManager(engineLog);
        }
        ~Utils()
        {
            delete configHandlePtr;
            delete logHandlePtr;
        }

        ConfigManager &configHandle() const { return *configHandlePtr; }
        LogManager &logHandle() const { return *logHandlePtr; }
};

下面是LogManager类的真正代码:

class LogManager
{
    protected:
        string mDefaultPath;

    public:
        LogManager(const string &logPath = "Engine.log") :
                mDefaultPath(logPath) { }

        void write(const string &message, const string logFile = "")
        {
            string workPath = mDefaultPath;


            Ogre::LogManager *logHandle = Ogre::LogManager::getSingletonPtr(); // [logHandle=0x000]
            Ogre::Log *log2Handle = logHandle->getLog(workPath); // [SEGFAULT]
            log2Handle->logMessage(message);

            Ogre::LogManager::getSingletonPtr()->logMessage(message);
        }
};

更新:

我有一个静态库(有我的引擎代码)和链接静态库的主要自己的程序。当我调用我的配置句柄(不使用 Ogre)时,一切正常!还有resourceManager,它也使用了Ogre。它像 logManager 一样失败。这两个经理都使用食人魔的单例。也许不可能从另一个库调用它?

最佳答案

感觉就像您拥有典型的“static initialization order fiasco”——您的 Utils 实例在其他一个(或两个)单例之前创建。

尝试将 Utils::configHandle() 更改为如下内容:

ConfigManager &configHandle() const {
    static std::auto_ptr<ConfigManager> configHandlePtr(0);
    if (!configHandlePtr.get()) {
       configHandlePtr.reset(new ConfigManager());
       // init configHandlePtr like you want
    }
    return *configHandlePtr;
}

关于c++ - 单例的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3015263/

相关文章:

c++ - OpenCV 断言失败且有 ROI

c++ - 我应该在使用之前检查 boost::shared_ptr 或 std::shared_ptr 吗?

c++ - 用户定义的字符串文字与常量字符串的比较

java - 如何在一个长的for循环中清空所有变量,避免程序内存不足?

c++ - * 之前预期的构造函数、析构函数或类型转换(第 45 行)

xaml - 即使获得开发人员许可,Visual Studio 2013(XAML?)Designer也会在所有Windows Phone项目上崩溃

java - 应用程序在运行构建时不断崩溃

singleton - "Singleton"工厂,好还是坏?

php - 构造单例类(class)

java - 在 Java 单例中使用静态?