Обнуление static атрибутов класса
От: R1K0 Россия  
Дата: 26.11.09 12:19
Оценка:
Всем привет.

Столкнулся с такой проблемой. Есть класс (урезано):

class cCacheSystem
{
    public:
        static string rootDir;
        static string cacheDir;
        static string pathToMetaFile;


Перед вызовом его конструктора я явно присваиваю значения:

cCacheSystem::rootDir        = s1;
cCacheSystem::cacheDir       = s2;
cCacheSystem::pathToMetaFile = s3;


Как только я закрываю приложение, вызывается деструктор объекта этого класса (одиночка), и в деструкторе я использую эти переменные, но они на тот момент являются пустыми строками. Насчет того, что они явно нигде не обнуляются, я уверен полностью, но факт остается фактом — я не могу их использовать и все плохо

Подскажите ПЛЗ где я не прав и что делаю не так.
Re: Обнуление static атрибутов класса
От: Tilir Россия http://tilir.livejournal.com
Дата: 26.11.09 12:53
Оценка:
Здравствуйте, R1K0, Вы писали:

RK>Подскажите ПЛЗ где я не прав и что делаю не так.


Скорее всего очередной обычный фейл, связанный с тем, что порядок деинициализации статических объектов не определён. Объект класса, который уничтожается деструктором, вполне может быть уничтожен после отработки деструкторов статических членов класса, при выходе из приложения. Как с раскруткой стека повезёт. Вам вот не повезло...

В общем: не полагайтесь в деструкторе на то, что статические члены ещё живы.
Re: Обнуление static атрибутов класса
От: rg45 СССР  
Дата: 26.11.09 12:54
Оценка: 2 (2) +1
Здравствуйте, R1K0, Вы писали:

RK>Всем привет.


RK>Столкнулся с такой проблемой. Есть класс (урезано):


RK>
RK>class cCacheSystem
RK>{
RK>    public:
RK>        static string rootDir;
RK>        static string cacheDir;
RK>        static string pathToMetaFile;
RK>


RK>Перед вызовом его конструктора я явно присваиваю значения:


RK>
RK>cCacheSystem::rootDir        = s1;
RK>cCacheSystem::cacheDir       = s2;
RK>cCacheSystem::pathToMetaFile = s3;
RK>


RK>Как только я закрываю приложение, вызывается деструктор объекта этого класса (одиночка), и в деструкторе я использую эти переменные, но они на тот момент являются пустыми строками. Насчет того, что они явно нигде не обнуляются, я уверен полностью, но факт остается фактом — я не могу их использовать и все плохо


RK>Подскажите ПЛЗ где я не прав и что делаю не так.


А для чего ты насоздавал такое количество открытых статических переменных?, У тебя же сам класс CacheSystem реализован как Sigleton, вот и сделай эти переменные закрытыми нестатическими членами этого класса. А для доступа к этим строкам заведи в классе методы, нестатические опять же.

Даже при реализации паттерна Singleton знание о том, что данный объет должен быть единственным, нужно стараться локализовать как можно сильнее. В идеале, если это возможно, реализация функций-членов класса вообще не должна полагаться на то, что данный объект будет синглтоном. И только один единственный метод класса реализует его как одиночку. А еще лучше стратегию владения объектом-одиночкой сделать внешней по отношению к классу, реализующему основную его функциональность. При таком подходе проблем с рефакторингом будет меньше и вероятность повторного использования кода возрастает.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Обнуление static атрибутов класса
От: Nik_1 Россия  
Дата: 26.11.09 12:57
Оценка:
Здравствуйте, Tilir, Вы писали:

T>Здравствуйте, R1K0, Вы писали:


RK>>Подскажите ПЛЗ где я не прав и что делаю не так.


T>Скорее всего очередной обычный фейл, связанный с тем, что порядок деинициализации статических объектов не определён. Объект класса, который уничтожается деструктором, вполне может быть уничтожен после отработки деструкторов статических членов класса, при выходе из приложения. Как с раскруткой стека повезёт. Вам вот не повезло...


T>В общем: не полагайтесь в деструкторе на то, что статические члены ещё живы.


Как вариант — можно явно запускать уничтожение этого синглтона до выхода из мейна.
Re[2]: Обнуление static атрибутов класса
От: R1K0 Россия  
Дата: 26.11.09 12:58
Оценка:
Всем спасибо за ответ. Буду копать дальше
Re[3]: Обнуление static атрибутов класса
От: Tilir Россия http://tilir.livejournal.com
Дата: 26.11.09 13:01
Оценка:
Здравствуйте, Nik_1, Вы писали:

T>>В общем: не полагайтесь в деструкторе на то, что статические члены ещё живы.


N_>Как вариант — можно явно запускать уничтожение этого синглтона до выхода из мейна.


Можно. Пока кто-нибудь не сделает exit() откуда-нибудь из середины приложения и всё снова рухнет. Если приложение WinAPI, то оно обычно так и завершится -- по закрытию окна. Или консольное -- по закрытию консоли крестиком задолго до выхода из main(). В принципе можно такие вещи конечно руками отслеживать... но в общем случае лучше без нужды вообще не рисковать.
Re[4]: Обнуление static атрибутов класса
От: Nik_1 Россия  
Дата: 26.11.09 13:37
Оценка: +1
Здравствуйте, Tilir, Вы писали:
T>Можно. Пока кто-нибудь не сделает exit() откуда-нибудь из середины приложения и всё снова рухнет.
За такое следует отрезать яйца, чтоб разработчики, делающий вызов exit() в модуле который ни коим боком не отвечает за время жизни приложения(а также его загрузку и выгрузку), не оставляли после себя потомство умственных инвалидов.
T>Если приложение WinAPI, то оно обычно так и завершится -- по закрытию окна.
Ничего подобного, в этом случаи всеголишь шлется сообщение WM_CLOSE. А нормальные разработчики если хотят при закрытии именно этого окна завершать приложение, то в обработчики сообщения WM_DESTROY этого окна вызывают PostQuiteMessage, которая в свою очередь выставит флаг что очереди обработки сообщений нужно завершиться. Соответственно после выхода из цыкла обработки сообщений приложение выполнит все необходимый действия для корректоного завершения и вернет управление из фанкции мейн.
T>Или консольное -- по закрытию консоли крестиком задолго до выхода из main(). В принципе можно такие вещи конечно руками отслеживать... но в общем случае лучше без нужды вообще не рисковать.
Консольное приложение — это отдельный и довольно извратский способ. Пользователь "сам дурак" если выходит из него по крестику, а не штатными методами.
Re[5]: Обнуление static атрибутов класса
От: Кодт Россия  
Дата: 26.11.09 20:15
Оценка: +1
Здравствуйте, Nik_1, Вы писали:

T>>Или консольное -- по закрытию консоли крестиком задолго до выхода из main(). В принципе можно такие вещи конечно руками отслеживать... но в общем случае лучше без нужды вообще не рисковать.

N_>Консольное приложение — это отдельный и довольно извратский способ. Пользователь "сам дурак" если выходит из него по крестику, а не штатными методами.

Почему это сам дурак?
Крестик приводит к signal(SIGINT), то же самое будет, если пользователь нажмёт Ctrl+Break (или Ctrl+C). Вполне себе штатное действие.
Если программа с претензиями на интерактивность, то она должна в обработчике сигнала взвести флажок, а в ходе основной работы этот флажок опрашивать, и как можно скорее выходить удобным безопасным способом.
Хотя в некоторых случаях безопасен будет и exit() прямо из обработчика сигнала.

Например, если программа записывает структурированные файлы, то транзакционность записи делается так:
— сперва пишем во временный файл (внезапный exit() приведёт лишь к мусорному файлу, если ОС не умеет стирать временные файлы по закрытии процесса)
— затем атомарно переименовываем его в целевой.
Перекуём баги на фичи!
Re[6]: Обнуление static атрибутов класса
От: Nik_1 Россия  
Дата: 26.11.09 21:09
Оценка:
Здравствуйте, Кодт, Вы писали:
К>Почему это сам дурак?
К>Крестик приводит к signal(SIGINT), то же самое будет, если пользователь нажмёт Ctrl+Break (или Ctrl+C). Вполне себе штатное действие.
Это вроде в юникс системах так, или я ошибаюсь? В сообщение на котороя я отвечал про винду говорилось. Но влюбом случаи, консольных прог в винде я особо много не писал, поэтому могу ошибаться как там все устроено
Re[7]: Обнуление static атрибутов класса
От: Кодт Россия  
Дата: 27.11.09 00:07
Оценка:
Здравствуйте, Nik_1, Вы писали:

К>>Крестик приводит к signal(SIGINT), то же самое будет, если пользователь нажмёт Ctrl+Break (или Ctrl+C). Вполне себе штатное действие.

N_>Это вроде в юникс системах так, или я ошибаюсь? В сообщение на котороя я отвечал про винду говорилось. Но влюбом случаи, консольных прог в винде я особо много не писал, поэтому могу ошибаться как там все устроено

И в досе, и в виндах тоже.
На самом деле, продвинутая консольная программа должна пользоваться продвинутым консольным апи (curses или ConsoleAPI), а не только и не столько SIGINT'ом.
Перекуём баги на фичи!
Re[7]: Обнуление static атрибутов класса
От: new_member Россия  
Дата: 27.11.09 08:03
Оценка:
Здравствуйте, Nik_1, Вы писали:

N_>Здравствуйте, Кодт, Вы писали:

К>>Почему это сам дурак?
К>>Крестик приводит к signal(SIGINT), то же самое будет, если пользователь нажмёт Ctrl+Break (или Ctrl+C). Вполне себе штатное действие.
N_>Это вроде в юникс системах так, или я ошибаюсь? В сообщение на котороя я отвечал про винду говорилось. Но влюбом случаи, консольных прог в винде я особо много не писал, поэтому могу ошибаться как там все устроено

В винде есть функция SetConsoleCtrlHandler, все виды нажатий пользователем, logoff и т.п. ловится через ее хэндлер.
Re: Обнуление static атрибутов класса
От: sanchosz  
Дата: 29.11.09 19:04
Оценка:
Здравствуйте, R1K0, Вы писали:

RK>Столкнулся с такой проблемой. Есть класс (урезано):


RK>
RK>class cCacheSystem
RK>{
RK>    public:
RK>        static string rootDir;
RK>        static string cacheDir;
RK>        static string pathToMetaFile;
RK>


Попробуй заменить члены класса на функции-гетеры:
static string getRootDir() {
    static string rootDir = "/root/dir";
    return rootDor;
}
Re[2]: Обнуление static атрибутов класса
От: Basil2 Россия https://starostin.msk.ru
Дата: 30.11.09 11:33
Оценка:
Здравствуйте, sanchosz, Вы писали:

S>Здравствуйте, R1K0, Вы писали:


S>Попробуй заменить члены класса на функции-гетеры:

S>
S>static string getRootDir() {
S>    static string rootDir = "/root/dir";
S>    return rootDor;
S>}
S>

Это только усугубит проблему, т.к. все равно неопределено, когда будут вызваны деструкторы статических членов.
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.