Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> сингелтон, сериализация в деструкторе 
V
    Опции темы
cupper
Дата 12.1.2011, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



делаю вот такую штуку

есть класс (сингелтон)
Код

class DatabaseHelper : private boost::noncopyable
    {
    friend class boost::serialization::access;
            template<class Archive>
            void serialize(Archive&, const unsigned int);
    public:
        static const DatabaseHelper& GetHelper();
        // При разрушении объекта сохраняем найтроки во внешний файл
        ~DatabaseHelper();
    private:
...

        static boost::shared_ptr<DatabaseHelper> theSingelton;
        /// Создает объект с использую дефолтные настройки
        DatabaseHelper();
        
        // Информация для подлкючение к БД
        std::string address_;
        std::string user_;
        std::string pwd_;
        std::string database_;

        /// Сохраняем данные во внешний файл, в xml формате
        void save();
        /// Загружаем настройки из внешнего xml файла
        /// если файл отсутствует, или не соответвует стандарту, загружаются настройки по умолчанию
        void load();
    };

    template<class Archive>
    void DatabaseHelper::serialize(Archive& ar, const unsigned int version)
    {
        ar & BOOST_SERIALIZATION_NVP(address_);
        ar & BOOST_SERIALIZATION_NVP(user_);
        ar & BOOST_SERIALIZATION_NVP(pwd_);
        ar & BOOST_SERIALIZATION_NVP(database_);
    }


Вот основные методы
Код

boost::shared_ptr<DatabaseHelper> DatabaseHelper::theSingelton = boost::shared_ptr<DatabaseHelper>();

    const DatabaseHelper& DatabaseHelper::GetHelper()
    {
        if(!theSingelton)
        {
            theSingelton.reset(new DatabaseHelper());
            theSingelton->load();
        }
        return *theSingelton;
    }

    DatabaseHelper::DatabaseHelper() :
        address_(SERVER_ADDRESS),
        user_(USER),
        pwd_(PASSWORD),
        database_(DATABASE)
    {
    }

    DatabaseHelper::~DatabaseHelper()
    {
        theSingelton->save();
    }
void DatabaseHelper::save()
    {
        try
        {
            std::ofstream ofs(SETTING_FILE_NAME);
            if(ofs.good())
            {
                std::cout << this->user_ << std::endl;
                boost::archive::xml_oarchive oa(ofs);
                oa << boost::serialization::make_nvp("queryString", *this);
                ofs.close();
            }
        }
        // если чтото пошло не так, пользователю знать об этом не обязательн
        catch(...)
        {
        }
    }
    void DatabaseHelper::load()
    {
        try
        {
            std::ifstream ifs(SETTING_FILE_NAME);
            if(ifs.good())
            {
                boost::archive::xml_iarchive ia(ifs);
                ia >> boost::serialization::make_nvp("queryString", *this);
                ifs.close();
            }
        }
        // если чтото пошло не так, используем настройки по умолчанию
        catch(...)
        {
            theSingelton.reset(new DatabaseHelper());
        }
    }


при заверншении программы вызывается по средством shared_ptr вызывается деструктор для объекта theSingelton, а в деструкторе вызывается функция для сериализации текущего состояния в файл. 

При работе программы (а вернее при ее завершении) получаю
Код

server: /usr/include/boost/serialization/singleton.hpp:131: static T& boost::serialization::singleton<T>::get_instance() [with T =
 boost::archive::detail::oserializer<boost::archive::xml_oarchive, DatabaseLayer::DatabaseHelper>]: Assertion `! 
detail::singleton_wrapper<T>::m_is_destroyed' failed.
Аварийный останов

ошибку вызывает строка
Код

ia >> boost::serialization::make_nvp("queryString", *this);

не врублюсь, в чем ошибка.

Это сообщение отредактировал(а) cupper - 12.1.2011, 22:43
PM MAIL   Вверх
mes
Дата 12.1.2011, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(cupper @  12.1.2011,  21:42 Найти цитируемый пост)
 вызывается деструктор для объекта theSingelton, а в деструкторе вызывается функция для сериализации текущего состояния в файл. 

код не смотрел.. но, мне кажется, Вам не помешает погуглить на темы : недостатки синглетонов и чем опасны деструкторы статических переменных.. 


--------------------
PM MAIL WWW   Вверх
cupper
Дата 13.1.2011, 09:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



ну о сингелтонах я раньше уже читал. Выбор сингелтона, тут не столько потребность в нем, сколько желание попробовать (ну и цель кажется оправданная, настройки подключения к БД должны быть одни). А вот по поводу деструктора статических переменных, вопсец есть, да я читал что они уничтожаются несколько иным образом чем другие объекты (а именно порядок удаления не определен) но у меня тут это и не важно, яже не делаю акцент на данные из вне. У меня класс получается замкнут в себе. Сам себе десераилзует при первом обращении к сеингелтону, и сам себя сериализует при вызове деструктора. 
Притом не важно делаю я сериализацию через *this и не статические функции load save, или же я наоборот делаю их статическими и сериализуют через указатель на объект theSingelton.

Проблема так и не прояснилась для меня. 
PM MAIL   Вверх
mes
Дата 13.1.2011, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(cupper @  13.1.2011,  08:28 Найти цитируемый пост)
я же не делаю акцент на данные из вне.

Цитата(cupper @  13.1.2011,  08:28 Найти цитируемый пост)
и сам себя сериализует при вызове деструктора. 

a сериализация разве не "данные из вне" ?

Цитата(cupper @  13.1.2011,  08:28 Найти цитируемый пост)
Притом не важно делаю я сериализацию через *this и не статические функции load save, или же я наоборот делаю их статическими и сериализуют через указатель на объект theSingelton.

ну так проблема то не с this-ом вашего класса.. а то что он пытается использовать уже разрушенные объекты...
перечитайте внимательно текст ошибки.. 



--------------------
PM MAIL WWW   Вверх
cupper
Дата 13.1.2011, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(mes @ 13.1.2011,  10:03)
ну так проблема то не с this-ом вашего класса.. а то что он пытается использовать уже разрушенные объекты...
перечитайте внимательно текст ошибки..

хм... перед непосредственно сериализацией данные они еще есть, распечатывал, получается что когда процесс передается сериализации то в этот момент данные разрушаются ?

А как это можно проверить, и можно ли как то преодолеть эту проблему. А то не хочется выносить сериализацию в отдельный метод и запускать ее ручками при выходе из программы.
PM MAIL   Вверх
mes
Дата 13.1.2011, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(cupper @  13.1.2011,  11:00 Найти цитируемый пост)
перед непосредственно сериализацией данные они еще есть,

данные чего ? вашего синглетона.. ну так конечно есть.. ибо деструктор еще в действии.. 
проблема у того, кому Вы эти данные передаете.. 

Цитата(cupper @  13.1.2011,  11:00 Найти цитируемый пост)
 А то не хочется выносить сериализацию в отдельный метод и запускать ее ручками при выходе из программы. 

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


сейчас посмотрю, что там у Вас с кодом.. 



--------------------
PM MAIL WWW   Вверх
mes
Дата 13.1.2011, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата

Код

  BOOST_DLLEXPORT static T & get_instance() {
        static detail::singleton_wrapper< T > t;          // <<<<<<<<<<<<<<<<< он уничтожился раньше вашего синглетона.. 
        // refer to instance, causing it to be instantiated (and
        // initialized at startup on working compilers)
        assert(! detail::singleton_wrapper< T >::m_is_destroyed);
        use(instance);
        return static_cast<T &>(t);
    }



Это сообщение отредактировал(а) mes - 13.1.2011, 13:58


--------------------
PM MAIL WWW   Вверх
cupper
Дата 13.1.2011, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(mes @ 13.1.2011,  13:33)
Цитата(cupper @  13.1.2011,  11:00 Найти цитируемый пост)
перед непосредственно сериализацией данные они еще есть,

данные чего ? вашего синглетона.. ну так конечно есть.. ибо деструктор еще в действии.. 
проблема у того, кому Вы эти данные передаете.. 

Цитата(cupper @  13.1.2011,  11:00 Найти цитируемый пост)
 А то не хочется выносить сериализацию в отдельный метод и запускать ее ручками при выходе из программы. 

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


сейчас посмотрю, что там у Вас с кодом.. 

ну а что ее там запускать будет ? Получается нужно будет ридумать еще какую то конструкцию над сингелтоном который бы в своем деструкте делал сериализацию сингелтона и потом только удалялся бы сингелтон. 

В голове крутиться идея, в деструкте сингелтона, создатьвать объект-копию уничтожаемого и его уже сериализовать. 


PM MAIL   Вверх
mes
Дата 13.1.2011, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(cupper @  13.1.2011,  13:27 Найти цитируемый пост)
Получается нужно будет ридумать еще какую то конструкцию над сингелтоном который бы в своем деструкте делал сериализацию сингелтона и потом только удалялся бы сингелтон. 

при чем тут Ваш синглетон ??? с ним все в порядке.. он жив на момент использования... а вот тот, который должен быть исполнить его последнюю волю, к сожалению, уже погиб..

Добавлено через 1 минуту и 44 секунды
Цитата(cupper @  13.1.2011,  13:27 Найти цитируемый пост)
В голове крутиться идея, в деструкте сингелтона, создатьвать объект-копию уничтожаемого и его уже сериализовать. 

еще раз перечитайте внимательно предыдущие посты.. 



--------------------
PM MAIL WWW   Вверх
cupper
Дата 13.1.2011, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(mes @ 13.1.2011,  14:37)
при чем тут Ваш синглетон ??? с ним все в порядке.. он жив на момент использования... а вот тот, который должен быть исполнить его последнюю волю, к сожалению, уже погиб..
...
еще раз перечитайте внимательно предыдущие посты..

я не могу понять чего вы мне говорите. Скажите прямо. Я дос сих порт так и не понял что вызывает ошибку.
PM MAIL   Вверх
mes
Дата 13.1.2011, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(cupper @  13.1.2011,  14:54 Найти цитируемый пост)
я не могу понять чего вы мне говорите. Скажите прямо. Я дос сих порт так и не понял что вызывает ошибку. 

есть два статических объекта.. один Ваш, один библиотечный.. Вы в деструкторе Вашего обращаетесь к библиотечному.. 
но.. библиотечный к тому времени уже уничтожен...

Добавлено через 54 секунды
Цитата(cupper @  13.1.2011,  14:54 Найти цитируемый пост)
 Скажите прямо. 


а тут разве не прямо ? :
Цитата(mes @  13.1.2011,  13:37 Найти цитируемый пост)
при чем тут Ваш синглетон ??? с ним все в порядке.. он жив на момент использования... а вот тот, который должен быть исполнить его последнюю волю, к сожалению, уже погиб..




--------------------
PM MAIL WWW   Вверх
cupper
Дата 13.1.2011, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(mes @ 13.1.2011,  15:59)
есть два статических объекта.. один Ваш, один библиотечный.. Вы в деструкторе Вашего обращаетесь к библиотечному.. 
но.. библиотечный к тому времени уже уничтожен...

ах тыж еп*ать черт блин заногу дери smile 

точно, яж не контролирую процесс удаление, сингелтон удаляется примерно тогда же когда и все другие объекты. Долго так доходило потому что я даже и не подозревал что сам механизм сериализации сам юзает статические объекты. 

Черт, тогда получается то что я пытался сделать вообще нельзя сделать. Черт я мне так понравилась задумка, авто сериализации :( 

блин, чеж делать тогда :(
PM MAIL   Вверх
mes
Дата 13.1.2011, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(cupper @  13.1.2011,  15:31 Найти цитируемый пост)
Черт, тогда получается то что я пытался сделать вообще нельзя сделать. 

скорее просто задумали не то что нужно..  smile 
что требуется то в общем (без оглядки на реализацию) ?
чтоб сериализовало некую БД по выходу из маин ?

можно например так :
Код

struct auto_saver 
{
     auto_saver (BD& bd) : _bd(bd) {
     }
     ~auto_saver (){
         _bd->save(); 
     }
  private:
     BD _bd;
};

BD bd;
int main ()
{
    auto_saver (bd);

//...   
     
} // <<< здесь произойдет запись.


Это сообщение отредактировал(а) mes - 13.1.2011, 17:05


--------------------
PM MAIL WWW   Вверх
cupper
Дата 13.1.2011, 20:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



деструктор auto_saver вызывается при выходе из main. А когда же тогда вызываелся дейструктов в моем коде ? я был уверен что также при выходе из main. Тогда в чем собстно разница ? Или же сдесь игра идет за счет того что создается стековый объект auto_saver деструктор которого вызывается 100% раньше чем для любых статических переменных ?

и кстати 
Код

auto_saver (BD& bd) : _bd(bd) {
     }

вы подразумеваете отказ от сингелтона как такового ?

И будет ли разница если сделать так
Код

struct auto_saver 
{
     auto_saver (BD* bd) : _bd(bd) {
     }
     ~auto_saver (){
         _bd->save(); 
     }
  private:
     // существует только один объект класс BD и мы можем хранить только указатель на него
     BD* _bd;
     // а лучьше всетаки shared_ptr<BD>
};


но все равно не понимаю концептуальной разницы между моим кодом и вашим. Тут и там сериализация происходит в деструкторе. Оба вызываются автоматически.
PM MAIL   Вверх
mes
Дата 13.1.2011, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(cupper @  13.1.2011,  19:10 Найти цитируемый пост)
вы подразумеваете отказ от сингелтона как такового ?

нет, в контексте данного вопроса, не отказываю Вам в синглетоне, как таковом smile 
а лишь призываю, не использовать в его деструкторе ничего внешнего.. smile

Цитата(cupper @  13.1.2011,  19:10 Найти цитируемый пост)
деструктор auto_saver вызывается при выходе из main

 smile 

Цитата(cupper @  13.1.2011,  19:10 Найти цитируемый пост)
 А когда же тогда вызываелся дейструктов в моем коде ?

гораздо позже.. smile

Цитата(cupper @  13.1.2011,  19:10 Найти цитируемый пост)
Тогда в чем собстно разница ?

во времени жизни.. 
в случае с автосейвером, он гарантировано уничтожится на выходе из мейн и гарантировано раньше, чем  уничтожатся синглетоны статические объекты..  в случае с синглетоном такой гарантии нет..

Цитата(cupper @  13.1.2011,  19:10 Найти цитируемый пост)
 Тут и там сериализация происходит в деструкторе. Оба вызываются автоматически. 

но в разные моменты времени smile см. выше..

Цитата(cupper @  13.1.2011,  19:10 Найти цитируемый пост)
но все равно не понимаю концептуальной разницы 

поэтому я изначально и предложил :

Цитата(mes @  12.1.2011,  22:05 Найти цитируемый пост)
чем опасны деструкторы статических переменных..  

но Вы почему то не отказали себе в этом удовольствии  smile  smile

а так бы съэкономили время и мне и себе  smile

Добавлено через 11 минут и 9 секунд
Цитата(cupper @  13.1.2011,  15:31 Найти цитируемый пост)
 сингелтон удаляется примерно тогда же когда и все другие объекты.

другие статические объекты и в неопределенном для пользователя порядке.. 


Цитата(cupper @  13.1.2011,  15:31 Найти цитируемый пост)
 потому что я даже и не подозревал что сам механизм сериализации сам юзает статические объекты. 

 smile, А Вы пробовали прочитать сообщение ошибки ? или это только для нас выложили :

Цитата(cupper @  12.1.2011,  21:42 Найти цитируемый пост)
server: /usr/include/boost/serialization/singleton.hpp:131: static T& boost::serialization::singleton<T>::get_instance() [with T =
 boost::archive::detail::oserializer<boost::archive::xml_oarchive, DatabaseLayer::DatabaseHelper>]: Assertion `! 
detail::singleton_wrapper<T>::m_is_destroyed' failed.

 smile 


Это сообщение отредактировал(а) mes - 13.1.2011, 20:40


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0984 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.