//非单例 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/