Атрибуты — Разница между .dtors и atexit () в переполнении стека

В чем разница между функциями в .dtors и функции, вызываемые с помощью atexit()?

Как я понимаю, функции помечены ((destructor)) атрибут находится в .dtors сегмент, и называется после выхода. Аналогично, функции добавлены с использованием atexit(fctName) помещаются в массив и также вызывается после нормального завершения выполнения.

Так почему же C ++ предоставляет здесь два разных механизма? Есть ли отдельные вещи, которые можно сделать только с одним? Могу ли я только добавить функцию динамически, используя atexit()?

Также которые называются во-первых, функции в .dtors или функции, добавленные с помощью atexit()?

0

Решение

От man-страницы linux atexit () вызывается при нормальном завершении процесса, либо через exit (3), либо через return из main () программы.

Что касается .ctors / .dtors, они вызываются, когда разделяемая библиотека, в которой они определены, загружается / выгружается.

Порядок, в котором они будут происходить, совершенно очевиден.

1

Другие решения

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

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

Для последней части вашего вопроса (и более подробную информацию) см. Когда функция, зарегистрированная с помощью atexit (), называется

0

Одной из законных реализаций деструкторов статических объектов является регистрация
их с atexit когда конструктор закончил. Стандарт
требует, чтобы порядок был таким же, как если бы использовалась эта реализация.
Основное отличие состоит в том, что деструкторы статических объектов являются
деструкторы: они будут вызваны автоматически, если объект
полностью построен, без необходимости с вашей стороны зарегистрироваться
их. И у них есть this параметр для доступа к объекту.

РЕДАКТИРОВАТЬ:

Чтобы было совершенно ясно: дано

T obj;      //  where obj has static lifetime...

Компилятор сгенерирует функцию:

void __destructObj()
{
obj.~T();
}

и следующий код инициализации:

new (&obj) T;
std::atexit( __destructObj );

Это независимо от объема obj; тот же основной код работает для
как локальная статика, так и объекты в области имен. (В случае
локальные объекты, компилятор также должен генерировать флаг и код
проверить его, чтобы указать, был ли объект уже инициализирован;
Также необходимо принять меры для обеспечения безопасности потока.)

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

-1