与单身人士的Segfaults

时间:2010-06-10 14:20:22

标签: 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()对象时无效

User program stopped by signal (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 一样失败。这两位经理都使用Ogre的单身人士。也许从另一个图书馆调用它是不可能的?

3 个答案:

答案 0 :(得分:1)

感觉就像你有典型的“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;
}

答案 1 :(得分:0)

我不知道Boost的单身人士,但我注意到你的'Utils'课上有些奇怪的东西。

首先,getHandle返回对handle的引用,但是如果你离开方法,handle是一个超出范围的局部变量,因此对它的引用也将无效。

其次,你没有在getHandle方法中初始化句柄。

答案 2 :(得分:0)

您确定您的Ogre LogManager已正确初始化吗?

或者你的库可能在每个库中都有一个单例实例,只有主程序中的一个实例被正确初始化了?

在这种情况下,您必须将库中的单例声明为“extern”,但我不确定它是否适用于静态链接库。