Проблемы с потерей конфиг файла

November 3rd, 2009 Begemot Posted in Программирование

Хочу пожаловаться, может кто поможет советом. Есть программы на написанные на wxWidgets и MFC, стартуют вместе с виндой и завершаются с ней же. При старте, как и рекомендует хелп делаю

wxFileConfig * config = new wxFileConfig(wxGetApp().GetAppName(), wxGetApp().GetVendorName(), dataPath + wxT("clipdiary.cfg")); // will be deleted by wxWidgets automatically

wxConfigBase::Set(config);

Потом периодически читаю\пишу, иногда, но не всегда делаю Flush(true). При выходе из программы и\или при получении сообщения EVT_QUERY_END_SESSION пишу кое-какие данные в цфг, делаю Flush(true). В самом конце делаю делаю вот такое

int MyApp::OnExit()
{
    // Баг, столкнулся с тем что почему-то не пишет в файл надо или flush или удалять указатель (при удалении он сам все пишет)
    // по идее библиотека должна сама удалять объек. но не удаляет. так что будем вручную.
    delete wxConfigBase::Set(NULL);       // Flush and delete config

    return wxApp::OnExit();
}

А проблема в том, что периодически (редко) при запуске программы – конфиг файл оказывается пустой, в смысле или совсем пустой или отсутствующий, не могу точно сказать. Программа при загрузке выдает сообщение ошибку wxWidgets, что-то типа “ошибка конвертации в юникод” точно не помню. Скорее всего проблема происходит при выключении компьютера, наверняка при каком-то “плохом” завершении работы. Раньше об этом писали пользователи, жаловались на то что пропадают настройки… Недавно поймал такое у себя – висели три мои программы на mfc, wxWidgets trunk и  2.8.10 – две последние потеряли все настройки, мфц’шная нет. Вот думаю куда копать и что делать, уже думал делать дублирование настроек во втором файле, но какой-то это странный путь 🙂 Может кто знает как сделать правильно?

 

Кстати, вот инструкция как реализовать ручную загрузку функций из DLL или как в программе использовать функции из Vista API?

Related:

13 Responses to “Проблемы с потерей конфиг файла”

  1. Я в подобном случае собрал работу с конфиг-файлом в отдельный объект. В методах, которым нужно прочитать или записать конфиг, инициализируется такой (локальный) объект. Чтение конфига у него в конструкторе, запись – в отдельном методе.
    “Плохое” завершение работы конфиг не трогает вообще.

  2. У меня работа с конфиг файлом происходит посредством собственных функций чтения/записи параметров. Причем, файл открывается – читается (пишется) параметр – закрывается. Проблем с потерей конфига не было даже при выключении питания.

    int LoadUserParam( const wxString &Param, int Default )
    {
    wxFileConfig *config = new wxFileConfig( wxEmptyString, wxEmptyString, GetUserConfigFile(), wxEmptyString, wxCONFIG_USE_NO_ESCAPE_CHARACTERS );
    wxFileConfig::Set( config );
    return config->Read( Param, Default );
    }

    bool SaveUserParam( const wxString &Param, int Value )
    {
    wxFileConfig *config = new wxFileConfig( wxEmptyString, wxEmptyString, GetUserConfigFile(), wxEmptyString, wxCONFIG_USE_NO_ESCAPE_CHARACTERS );
    wxFileConfig::Set( config );
    config->Write( Param, Value );
    config->Flush();
    return true;
    }

    Кстати, а почему wxConfigBase::Set(config)?

  3. Ну вы жесткие пацаны, на каждый чих открывать\закрывать конфиг, я до такого не додумался 🙂 Неужели переписывать все…

    Сергей: Кстати, а почему wxConfigBase::Set(config)?

    А чо нет? что должно быть?

  4. Зато надёжно 🙂 Хотя я собирался переделать его для блочного доступа, но теперь будем смотреть что у тебя получится.
    Для wxFileConfig * config более красивым выглядит
    wxFileConfig::Set( config ), но это только с эстетической точки зрения, поэтому я и поинтересовался, с какой целью вызывается wxConfigBase::Set(config)?

  5. Есть еще вариант вынести в отдельный конфиг-файл настройки программы (те, которые пользователь задает в диалоге Options).
    Читаться они могут беспрепятственно, а запись жестко локализуется ОК’ем диалога Options. Подозреваю, что пользователей волнует слет именно этих настроек.
    А остальную шелуху (запоминание последней позиции окна etc) оставить, как есть – слетит, так и черт с ней…

  6. Да настройки не только в диалоге программы, есть же еще галочки в меню, да и состояния окон, элементов тоже…
    Уж тогда лучше действительно копировать файл, делая резервную копию 🙂

    Буду в ближайшем будущем разбираться.

  7. Однако, интересно знать, куда деваются настройки?
    Теоретически, при любом сбое файл настроек должен ведь сохраниться. Я вижу пока только одну возможность – в момент flush когда он уже пометил старый файл пустым и не успел записать данные.

  8. Резервное копирование либо не запомнит последних изменений (если будет делаться при запуске программы), либо еще затормозит сохранение настроек (если будет делаться перед ним).

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

    А то, может… у реестра вроде бы запись должна быть атомарной? 😉

  9. Еще пару замечаний:
    1. Исходники wxWidgets можно не теребить – аналогичная фигня у меня была под MFC и с использованием ofstream. Были и более странные глюки – типа файла нужного размера, заполненного 0x00.
    2. Вариант Сергея, подозреваю, на самом деле вовсе не дергает зря винт – его микрозапросы прекрасно кэшируются, и чтение может быть произведено всего один раз, а запись быстренько встает в очередь и не убивается вместе с программой. Может, это как раз оптимум. Или я идеализирую нынешние системы?

  10. Adamos: Все-таки проблема, видимо, проявляется, когда запись настроек вызывается деструктором объекта. И решение, имхо, вытащить запись из деструктора.

    нет, думаю что проблема при записи в момент выключения компьютера, после получения сигнала об этом…

  11. Я, собственно, это и имел в виду – что после получения сигнала о выключении программа бросается записывать свой конфиг. Если при этом была загружена, например, Опера с настройкой “очищать кэш при выходе”, то до винта не достучаться. Вопрос локализуется: нужно ли программе записывать свои настройки при выходе или эту запись можно перенести на другие события, пока машина не в аврале?

  12. К сожалению у меня тут лично-рабочий аврал, поэтому я пока не занимаюсь этим:( может через неделю смогу.

    Тогда потестю разные варианты, пока есть мысль может просто то что _нужно_ сохранять при выключении, перенести в другой конфиг 🙂

  13. В виртуалке поставил обе программы, в автозагрузку добавил команду перезагрузки системы через две минуты. И так оно крутилось часов 6. Ничего не потерялось 🙁