[C++] деструкторы статических объектов

Realist

У меня есть статический объект A, у которого нетривиальный деструктор. Этот диструктор вызывает функцию из другого модуля. В том модуле та функция пользует какой-то свой статический объект B. Ну и по стечению обстоятельств к моменту вызова деструктора А этот второй объект B уже разрушен. Все это падает с треском.
Единственная рекомендация на сей счет, которую я встречал, состоит в избегании глобальных переменных. Есть ли еще какие-то практики, или же явные указания, о том, как обезопасить себя?
Например, когда я проектирую класс, я предполагаю, что кто-то когда-нибудь попробует выполнить присваивание и реализую оператор = (запрещаю копирование...).
Должен ли я полагать, что когда-нибудь кто-нибудь захочет создать глобальный объект моего класса? Или я должен всегда реализовывать деструктор так, чтоб он не вызывал функций за пределами данного файла? Должен ли я, когда пишу функции, подумать о том, что они используют статические переменные? Могу ли я в деструкторе вызывать стандартные функции?
Полагаю, такой же отстой можно поиметь и с нетривиальными конструкторами...

Dasar

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

kruzer25

Вообще, афаик, считается стандартной практикой то, что, если твой деструктор делает какие-то нетривиальные вещи, используя какие-то другие объекты - это не подходит для деструктора, и тебе нужен объект с явным временем жизни (см. IDisposable).

Serab

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

Serab

А есть C++, где деструктор — это единственный способ задать явно время жизни объекта и отдать гарантию выполнения этого требования на откуп компилятору.

kruzer25

Чорд, мне показалось, что в заголовке четыре плюса, а не два :ooo:
Но это ничего не меняет; мне кажется, что даже в плюсах разработчик не должен хотеть делать что-то сложное в деструкторе долгоживущего объекта.

Serab

С точки зрения разработчика класса к проблеме действительно подобраться кажется сложным, надо копать от функции.
Если у тебя есть функция, явно работающая с глобальными данными, то надо понимать, что позвать ее могут откуда угодно (она же глобальная а поэтому обеспечить соответствующим глобальным объектам наиболее объемлющее время жизни: убрать их в общий файл, которому поставить приоритет инициализации (конкретный способ, естественно, зависит от компилятора, можешь погуглить).

Serab

Так в том-то и вопрос: человек спрашивает, как проектировать класс, когда он не знает, кому как взбредет в голову его использовать.
А вообще да, деструктор C++ и финализатор .NET — это вещи, имеющие очень мало общего.

kruzer25

человек спрашивает, как проектировать класс, когда он не знает, кому как взбредет в голову его использовать.
Можно подумать, что объект этого класса сам по себе где-то существует синглтоном, пока кто-то внезапно не позовёт у него деструктор.

Dasar

Есть класс, написанный одним программистом, другой где-нибудь описал глобальную переменную этого типа.
и вот экземпляр этой глобальной переменной должен создаваться по первому требованию.

kruzer25

В случае с циклическими зависимостями это не поможет. Думать всё равно надо.

Dasar

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

kokoc88

Единственная рекомендация на сей счет, которую я встречал, состоит в избегании глобальных переменных.
Можно заменить глобальные переменные на указатели, и тогда у тебя будет контроль над тем, что происходит. А вообще проблема достаточно стандартная, часто происходит в сторонних С++ on C библиотеках типа Qt.

kruzer25

с циклами вообще ничего не поможет, кроме их развязывания
Надо изначально писать так, чтобы было чётко видно, в каком порядке создаются/уничтожаются такие долгоживущие "глобальные" объекты.
но в исходном посте - проблема не с циклами.
"Правильная" борьба с циклами решит и проблему в исходном посте.

Serab

"Правильная" борьба с циклами решит и проблему в исходном посте.
вопрос был: как не создавать подобных проблем, требовались простые четкие правила.

Serab

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

class A;

A x;

int y = reinterpret_cast<int>( &x ) + 18;

когда надо создавать x?

asvsergey

что значит «должен»? Как программист может на это повлиять?

Повлиять можно, синглетоном если класс сделать.

okis

Это обходной путь. Если куча GSO уже есть проблемы такой не избежать.

asvsergey

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

Serab

Т.е. предлагается *каждую* глобальную переменную окружать в синглтон?
Придется выдумывать им имена и объяснять другим программистам, что это вот так у нас забацаны глобальные переменные.
Это еще и не решит проблемы с деструкторами, но будет вырвиглазная кривота. Ты видел такое в коммерческом коде? Я — нет, и проблемы с порядком инициализации решены. Нормальный подход к решению я описал выше.

asvsergey

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

asvsergey

Придется выдумывать им имена и объяснять другим программистам, что это вот так у нас забацаны глобальные переменные.
Это еще и не решит проблемы с деструкторами, но будет вырвиглазная кривота. Ты видел такое в коммерческом коде? Я — нет, и проблемы с порядком инициализации решены. Нормальный подход к решению я описал выше.

А переменным имена не надо придумывать?
Чего то я не понял, ты считаешь, что лучше использовать глобальные пременные, чем синглетоны, да еще и в комерческом проекте?

elenangel

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

kruzer25

вопрос был: как не создавать подобных проблем, требовались простые четкие правила.
Простые чёткие правила - надо явно управлять жизнью таких "долгих" объектов в одном месте; а когда это будет сделано - в этом самом месте сделать так, чтобы нужный объект финализировался не позже используемого его финализатором.

Serab

да еще и в комерческом проекте?
:grin: а тебя так пугает это сочетание слов? Мы синглтонией не страдаем :grin:

Serab

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

kruzer25

Попробуй прочитать мой пост и понять, что "финализатором" я просто называю некоторый явно вызываемый метод. Мог бы назвать горшком, а назвал финализатором.

Serab

Это не C++-way.

asvsergey

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

kruzer25

Это не C++-way.
C++-way - писать плохо?

Serab

Мимо (это я тебе).

Serab

Я ничего не говорил про большое, я говорил про то, что мы не пугаемся глобальных константных строк, которые являются довольно хитрыми объектами, зависящими от глобальных данных. И не оборачиваем их в синглтоны. Еще есть некоторые специальные глобальные классы, к которым по сути прямого обращения и нет (не вдаюсь тут в детали). В общем мы знаем что делаем, а не боимся языка :D

asvsergey

Ну переменная не есть константа, это даже из названия видно :)
Надеюсь константные глобальные строки зависят от константных глобальных данных?
А то как то странно получтся.

Serab

Знаешь, что такое аллокаторы памяти в C++?

Serab

Ладно, не буду даже все усложнять, просто скажу:
1) можешь убрать из моего поста слово «константные», ибо неконстантные мы тоже используем. И использование это ограничивается не боязнью нарваться на зависимости от порядка инициализации, а из соображений дизайна;
2) с константными объектами все описанные неприятности сохраняются, они ничем не лучше и не хуже;
3) нечего играть словами «константа», «переменная», если экземпляр класса — то сразу переменная, то, что у нее нельзя напрямую вызвать неконстантные методы — это уже другой вопрос.

Andbar

Меня удивляет, что вы используете большое количество глобальных переменных в крупном проекте.
Нет ничего плохого в глобальных переменных, доступных только в одной единице компиляции. Во всяком случае, если это не вызывает проблем с многопоточностью.
По поводу общих глобальных переменных и синглтонов, тут есть три вопроса:
1. синглтон или не синглтон - целиком определяется требуемой функциональностью, если нужно гарантированно не более одного объекта, то используем синглтон, в противном случае - что-то другое;
2. нужно создание по требованию или создание в начале работы - определяется как требованиям к коду, так и ответом на 1й вопрос (синглтон обычно создаётся при первом обращении);
3. использова объект(ы)-обёртку/статический метод класса, либо глобальные переменные для доступа к экземпляру(ам): если в одном из первых вопросов выбран первый вариант, то решение без глобальной переменной уже, по идее, должно быть, в противном случае не всё так однозначно.

Ivan8209

А вас не удивляет наличие большого числа глобальных переменных в
libc/libstdc++? В ядре?
Более того, многие из них являются локальными.
Этот кошмар, по-видимому, должен просто добить.
---
"Quae medicamenta non sanat, ferrum sanat,
quae ferrum non sanat, ignis sanat."

asvsergey

Да я и не говорю, что глобальный объект это что то плохое.
Плохо когда их много.

Serab

Ну в libc, положим, никуда и не уйдешь от этого, потому что libc — это отдельный объект, который должен сохранять состояние между обращениями к нему.
Да там такой жести и не возникает, насколько я знаю.

Andbar

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

asvsergey

Миллион точно плохо :)
Развели тут спор, вы хотите убедить меня, что глобальные объекты делают потому, что это хорошо и красиво, а не тогда, когда по другому сделать нельзя или очень сложно?

Ivan8209

> Ну в libc, положим, никуда и не уйдешь от этого, потому что
> libc — это отдельный объект, который должен сохранять
> состояние между обращениями к нему.
Сомнительно.
Дублирование API (syslog_r, strerror_r, ttyname_r, ctime_r, getpwent_r
и много других "_r") только подтверждает сомнительность твоего заявления.
---
Q7: А что за suxx?
A7: unix.

Andbar

Миллион точно плохо :)
Чем плох g_my_favourite_class_instance[1000000]?
потому, что это хорошо и красиво, а не тогда, когда по другому сделать нельзя или очень сложно?
Какой-нить g_my_class_instance явно лучшее чем CMyClass::GetInstance если классов не слишком много. Просто лишние два двоеточия и скобочки не всегда себя оправдывают.

asvsergey

Чем плох g_my_favourite_class_instance[1000000]?

Тем что памяти отожрет 1000000*sizeof(g_my_favourite_class_instance)
и вызовет столько же конструкторов в момент старта приложения.
Какой-нить g_my_class_instance явно лучшее чем CMyClass::GetInstance если классов не слишком много. Просто лишние два двоеточия и скобочки не всегда себя оправдывают.

Синглетон нужен когда, надо отсрочить инициализацию, или есть вероятность, что объект никогда не понадобится, а не для красивой записи, т.к. по сути это то же глобальный объект.

asvsergey

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

Andbar

Синглетон нужен когда, надо отсрочить инициализацию, или есть вероятность, что объект никогда не понадобится, а не для красивой записи, т.к. по сути это то же глобальный объект.
Я рассматриваю вариант, когда синглтон в принципе не требуется.
Тем что памяти отожрет 1000000*sizeof(g_my_favourite_class_instance)
и вызовет столько же конструкторов в момент старта приложения.
памяти отожрёт ровно 1*sizeof(g_my_favourite_class_instance а если вдруг смысл будет в самих конструкторах и деструкторах, а не в данных, то sizeof(g_my_favourite_class_instance[0]) вовсе может оказаться равным нулю :grin: Короче, всё зависит от задачи и пока мы не рассматриваем какие-то конкретные примеры, спор будет бессмысленным.

Andbar

Мне кажется, вы неправильно поняли, я написал что синглетон можно использовать, для того что бы влиять на время создания глобального объекта, и это не имеет никакого отношения, к тому, что я считаю, что большое количество глобальных объектов не есть хорошо, т.к. синглетон тоже глобальный объект.
ну я вроде ещё раньше расписал, что в этом обсуждении смешаны три проблемы выбора (единственность экземпляра, время создания и использование глобальной переменной или какой-либо обёртки две из которых не относятся ко вкусам, а выбор в третьем случае зависит от выбора в первых двух.

asvsergey

Ну разве не плохо, когда у тебя нет выбора и приходится создавать кучу глобальных объектов :)

Serab

Да, понял. Вот это, кстати, странно: ладно, о потоках никто не думал, когда создавали эти crt и libc, но о реентерабельности-то можно было догадаться. Хотя об этом предупреждают, наверное, в манах.
Кстати, не видел этих функций, более того, на моей состеме find /usr/include/ -iname \*.h -print0|xargs -0 grep -H syslog_r ничего не находит.

Andbar

Ну разве не плохо, когда у тебя нет выбора и приходится создавать кучу глобальных объектов :)
выбор есть почти всегда. Тем более что случаев, когда глобальные объекты являются вполне приемлемым решением, конфигурационно меньше (хотя, статистически именно такой вариант может чаще встречаться в небольших проектах или при определённом стиле).

Ivan8209

> Вот это, кстати, странно: ладно, о потоках никто не думал,
> когда создавали эти crt и libc, но о реентерабельности-то
> можно было догадаться.
Во времена Unix v.7 не задумывались об этом.
> Кстати, не видел этих функций, более того, на моей состеме
> find /usr/include/ -iname \*.h -print0|xargs -0 grep -H syslog_r
> ничего не находит.

HISTORY
These non-multithread-safe functions appeared in 4.2BSD. The multi-
thread-safe functions appeared in OpenBSD 3.1 and then in NetBSD 4.0.
The async-signal-safe functions appeared in NetBSD 4.0. The syslog-pro-
tocol functions appeared in NetBSD 5.0.

---
A44: Ламеры в гамаке пусть в тапках трахаются --- это их проблемы.
Я в своём гамаке хочу полноценно трахаться на лыжах.

Dasar

что значит «должен»? Как программист может на это повлиять?
Что значит «требование»?когда надо создавать x?
очень и очень странно.
дожили до таких седин, а пугаетесь слова синглетон, и не знаете как синглетон дешево делается на C++
описание static переменной
A a;

можно заменить на такой код

inline A& a
{
static A _a;
return _a;
}

или такой код

inline A& a
{
static A * _a = new A;
return *_a;
}

и переменная a будет создаваться по первому требованию(при первом использовании а не при старте программы.

kokoc88

и переменная a будет создаваться по первому требованию(при первом использовании а не при старте программы
Ой, а как там всё интересно, когда a вызывается сразу из нескольких потоков...

Serab

Прикольно. Второй пример, правда, не понял, зачем утечку памяти создавать.
Но подобного я и правда нигде не видел. Точно не уверен, как к этому отнесутся коллеги =)

Dasar

Второй пример, правда, не понял, зачем утечку памяти создавать.
там нет утечки памяти, т.к. определение утечки памяти гласит - что память выделена и переменных ссылающихся на этих память уже не осталось.
зато память потребляется только если действительно переменная использовалась, в первом примере - память отъедается сразу (но инициализируется по первому использованию)

Serab

Ок, но то, что не вызван деструктор, уже плохо.

Dasar

Ой, а как там всё интересно, когда a вызывается сразу из нескольких потоков...
T& GetInst
{
static T t;
return t;
}
The current version of the standard completely ignores the existence of
threads (and almost completely ignores the existence of dynamic
libraries). Therefore, the code is not thread safe. But you can use
environment-specific means to make e.g. the initialization of the static
variable thread safe. One simple way is to call GetInst when only the
main thread has started, no others yet started. Another way, less
efficient, to ensure mutual exclusion for calls to GetInst. A third
way, if it's OK to let each thread have its own T object, to use thread
local storage. Boost threads support all three solutions. Of course,
the first one doesn't require any special support, so the support
consists of nothing, but by definition it's there...

kokoc88

Полный отстой:
One simple way is to call GetInst when only the main thread has started == глобальная переменная.
Another way, less efficient, to ensure mutual exclusion for calls to GetInst == лочим мьютекс на каждый вызов функции.
A third way, if it's OK to let each thread have its own T object, to use thread local storage == не синглтон.

apl13

Так это все не методы сделать thread-safe синглетон. Это воркараунды на случай если очень надо.

Andbar

А почему не упомянуть реализацию синглтона с блокировкой и двумя проверками? Конечно, это дело надо правильно реализовывать (в т.ч. с учётом особенностей платформы но при этом минимизируются накладные расходы.
Помнится, я когда-то уже примерный код шаблонного класса, при добавлении которого в родители класс становится синглтоном. При доведении этого дело до потокобезопасной реализации, получится, имхо, более понятная вещь, нежели стандартный для синглтонов вариант. Впрочем, я сейчас подумал, что если объединить оба варианта, получится ещё один бонус: экземпляр не будет занимать место в куче.

apl13

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

Andbar

А смысл? Тредобезопасности это не добавляет.
при правильной реализации и не убавит, зато добавит скорости (блокировки будут вызваться только примерно в момент создания экземпляра).

margadon

видел несколько разных реализаций синглтонов
по-моему, гуманнее заранее в архитектуре предусмотреть инициализацию всех необходимых синглтонов однотредно, нежели долго и кропотливо отлаживать синглтон на принципе Double check-а и бояться, что от смены компилятора или на другой платформе всё снова развалится

evolet

One simple way is to call GetInst when only the main thread has started == глобальная переменная.
== глобальная переменная, но без проблем с неопределенностью порядка инициализации в разных единицах трансляции.
)
так что это имхо все-же чуть лучше, чем "глобальная переменная" для сложных a

Serab

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

kokoc88

== глобальная переменная, но без проблем с неопределенностью порядка инициализации в разных единицах трансляции.
Для этого достаточно более простого решения: объявляем указатель. И ещё с указателем можно будет проверять утечки памяти какими-нибудь стандартными средствами.

Serab

О, и кстати, по поводу "чтения книжек". Маерс очень пугал своих читателей тем, что если вдруг, ну мало ли, вызов этой хитрой функции a не встроится, то есть шансы получить вообще красивое поведение: по копии A на единицу трансляции. От этого нынче не все компиляторы страдают, да, но все же, это плохое решение еще и поэтому.

Serab

Хм, прикольно. Оффтоп, но все же, любопытно


struct A {
A { printf( "A created\n" ); f; }
~A { printf( "A destroyed\n" ); }
void f;
};

struct B {
B { printf( "B created\n" ); f; }
~B { printf( "B destroyed\n" ); }
void f;
};

A& GetA
{
static A _a;
return _a;
}

B& GetB
{
static B _b;
return _b;
}

void A::f { printf( "A::f\n" ); GetB; }
void B::f { printf( "B::f\n" ); GetA; }

int main
{
GetA;
return 0;
}
Под g++ это падает, "recursive init". Под студией работает, но объекты удаляются в неправильном порядке.

procenkotanya

> мало ли, вызов этой хитрой функции a не встроится, то есть шансы получить вообще красивое поведение: по копии A на единицу трансляции
На самом деле Майерс так писал? Бред же полный.
> От этого нынче не все компиляторы страдают
Очень интересно. Какие страдают? Какие страдали в прошлом?

Serab

Бред же полный.
ниче не бред. Пока не настала стадия линковки, так и есть, потому что входные файлы обрабатываются независимо.
Но вообще это я в качестве шутки написал. Просто не люблю писать inline, не считаю себя умнее компилятора в вопросах оптимизации.

Serab

Очень интересно. Какие страдают? Какие страдали в прошлом?
можешь узнать, если интересно :grin:

evolet

вообще мне кажется, что эта какая-то проверка в gcc, потому что ты дошел
до

{
static A _a;
return _a;
}

когда у тебя еще конструктор А от первого вызова не отработал
в реальной жизни такое, я думаю, полюбас приведет к проблемам, даже если бы тут возвращался еще не полностью сконструированный объект (как делает студия, я подозреваю)

bely

Мне в свое время при аналогичной проблеме с порядком инициализации/деинциализации статических объектов помогло гугление по "static initialization order fiasco" - нашлась какая-то ссылка, где были разжеваны возможные варианты лечения. Не помню уже точно детали - но наверно должно помочь, например, следующее:
В большинстве компиляторов порядок деинициализации объектов - обратный порядку инициализации. Соответвенно достаточно выстроить порядок инициализации - а его довольно легко сделать правильным, например обернув тот статический объект,который должен инициализироваться первым внутрь функции, и делая доступ к объекту через эту функцию.

static CMyClass& GetMyStaticObject
{
static CMyClass myStaticObject;
return myStaticObject;
}

Т.е. в твоем примере я бы попробовал в конструкторе A дернуть фукцию, обертывающую B - тогда B создастся раньше и деинициализируется позже.

procenkotanya

Пока не настала стадия линковки, так и есть, потому что входные файлы обрабатываются независимо.
И при чём тут инлайнинг? Сколько будет копий А на единицу трансляции, если a заинлайнится?
Я пока не вижу логики в твоих словах.

Serab

Да, действительно странно. Но в любом случае это должно быть багой в компиляторе. Но завтра буду на работе, посмотрю в книжку, напишу, где конкретно он это писал. Что-то нагуглить не могу.
Похоже, что какой-то компилятор при невозможности заинлайнить просто заменял inline на static. Но это криминал, да :(

Serab

Все-таки меня не покидает мысль, что это гнилое решение этой проблемы и синглтон притянут за уши.
Но Маерс в More Effective C++ Item 47 рекомендует поступать именно так :grin:

Serab

Мда, рассуждения действительно странные, но Маерс пишет об этом в той же книге More Effective C++ в Item 33 (страница 133 русского издания).

trobak

Если будешь пробовать решать эту проблему при помощи синглтонов, то могу посоветовать посмотреть главу 6 "Современное проектирование на C++" Александреску. Там он довольно подробно разбирает, какие могут быть способы удаления синглтонов, в зависимости от того, какую стратегию их жизни ты выберешь (на сколько я помню, в книжке про шаблоны "Банды четырех" вопрос о времени жизни синглтонов просто обойден молчанием).
Краткий вывод такой: если есть зависимость между синглтонами, то одновременно просто и хорошо не будет по любому. Однако есть разные варианты со своими плюсами и минусами :)
Может, тебе какой и поможет. Например, B надо делать или
а) "фениксом" (если удалили, но потом опять обратились, то пусть создается)
или
б) определять целочисленные индекс, ранжирующий жизнь объекта (чтобы гарантировать, что синглтон переживет все объекты с меньшим индексом и тогда проектировать так, чтобы "младшие" синглтоны в своей реализации не зависели от старших.
(Ну, разумеется буквально также кодировать, как он предлагает, или использовать библиотеку Loki я не предлагаю, но полезные идеи оттуда извлечь можно.
Ну и это все при условии, что мы оставили в стороне разговоры вроде, "синглтон - это глобальная переменная в овечьей шкуре" и его использовать нельзя наравне с goto :)

procenkotanya

Ага, оказывается, стандарт языка и книжка были исправлены ещё в 1996 году:


! 5/15/96 sdm 134 Add footnote: 9/26/96
In July 1996, the ISO/ANSI standardization
committee changed the default linkage of inline
functions to external, so the problem I
describe here has been eliminated, at least on
paper. Your compilers may not yet be in accord
with the emerging standard, however, so your
best bet is still to shy away from inline
functions with static data.


6/22/98 sdm xiv Borland is now Inprise. 6/27/98

...

1/28/08 sdm xiv Borland is no longer Inprise. 1/28/08

Realist

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

Serab

А зачем вообще писать так, как во втором примере?

Realist

Не знаю, я этого не предлагал :)
Кстати, я так понял, что такой способ позволит программе не падать. Положим, сначала вызвались деструкторы в данном модуле трансляции, а теперь работает деструктор в другом модуле и вызывает эту функцию a. Думаю, нам никто не обещал, что мы можем помацать A*, но в реальности с самим указателем вряд ли что успело произойти, что его прочитать нельзя, правильно?

Realist

И теперь эта функция a лежит в dll, которая во время работы сервера туда-сюда 10 загружается и выгружается. Потечет?

Serab

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

Serab

Потечет?
Если допустить, что разговор о винде, то если A выделен на куче процесса (тот же malloc, через который по умолчанию работает new, в реализации CRT by Microsoft выделяет именно там то точно потечет.

Dasar

И теперь эта функция a лежит в dll, которая во время работы сервера туда-сюда 10 загружается и выгружается. Потечет?
для каких практических задач используется выгрузка dll, с последующей повторной загрузкой?

Realist

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

Dasar

У меня пример умозрительный. На практике такое бывает? Если придумаю практический пример, напишу.
мне цель этого действия не понятна.
сэкономить память за счет выгрузки dll-ки? такое может быть только, если dll-ек очень и очень много.
например, при генерации dll-ек, но почему тогда код просто в памяти не генерится?
Оставить комментарий
Имя или ник:
Комментарий: