Сегфо с синглетонами - PullRequest
0 голосов
/ 10 июня 2010

// Non 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);
        }
};

UPDATE:

У меня есть статическая библиотека (есть код моего двигателя) и основная собственная программа, которая связывает статическую библиотеку. Когда я вызываю мой дескриптор конфигурации (который не использует Ogre), все в порядке! Существует также resourceManager , он также использует Ogre. И это терпит неудачу как logManager . Оба этих менеджера используют синглтон Огре. Может быть, это невозможно назвать из другой библиотеки?

Ответы [ 3 ]

1 голос
/ 11 июня 2010

Такое ощущение, что у вас типичный " статический порядок инициализации фиаско " - ваш экземпляр 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;
}
0 голосов
/ 10 июня 2010

Вы уверены, что ваш Ogre LogManager правильно инициализирован?

Или, может быть, с вашими библиотеками у вас есть один экземпляр синглтона в каждой библиотеке, и только один в вашей основной программе правильно инициализирован?1004 * В этом случае вы должны объявить синглтоны в своих библиотеках как "extern", но я не уверен, что это применимо к статически связанным библиотекам.

0 голосов
/ 10 июня 2010

Я не знаю синглтона Буста, но замечаю некоторые странные вещи в вашем классе 'Utils'.

Прежде всего, getHandle возвращает ссылку на дескриптор, но handle - это локальная переменная, которая выходит из строя.области видимости, если вы покинете метод, поэтому ссылка на него также будет недействительной.

Во-вторых, вы не инициализировали дескриптор в методе getHandle.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...