В чем разница между __cxa_atexit () и atexit ()

в GCC документы Я нашел -fuse-cxa-atexit вариант и говорит следующее:

Эта опция требуется для полностью совместимой со стандартами обработки статических деструкторов

Так в чем же разница между этими двумя? В документах для __cxa_atexit Я нашел следующее:

Функция __cxa_atexit () используется для реализации atexit ()

Я реализую статику в функциях (не спрашиваю почему), и мне было интересно, какой из 2 использовать для вызова деструктора.

И я думаю, у меня есть только atexit() для MSVC? Это проблема?

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

4

Решение

__cxa_atexit() определяется в Itanium C ++ ABI. Документ объяснил мотивация этой функции:

Стандарт C ++ требует, чтобы деструкторы вызывались для глобальных объектов при выходе из программы в обратном порядке построения. Большинство реализаций справились с этим, вызвав библиотеку C atexit рутина для регистрации деструкторов. Это проблематично, поскольку стандарт C 1999 года требует только того, чтобы реализация поддерживала 32 зарегистрированных функции, хотя большинство реализаций поддерживают гораздо больше. Более важный, в большинстве реализаций он вообще не работает со способностью удалять [динамические общие объекты] из образа работающей программы, вызывая dlclose до завершения программы.

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

Так:

  • __cxa_atexit() не ограничено 32 функциями.
  • __cxa_atexit() вызовет деструктор статики динамической библиотеки, когда эта динамическая библиотека выгружается до выхода из программы.

Вы должен включить -fuse-cxa-atexit если вы пишете библиотеку, и ваша библиотека имеет эту функцию (например, glibc, musl). На самом деле, в gcc, поставляемом с вашим дистрибутивом, этот флаг уже может быть включен автоматически (будет ошибка компоновщика, если вы включите этот флаг, а libc не будет его поддерживать).

Обратите внимание, что пользователи не должны звонить __cxa_atexit непосредственно: принимает аргументы, которые должен знать только компилятор / компоновщик ( __dso_handle).

… Нет пользовательского интерфейса для __cxa_atexit поддерживается, поэтому пользователь не может зарегистрировать atexit функция с параметром или домашний DSO.


MSVC видимо не использует atexit()подобные функции запустить глобальные деструкторы. И согласно Деструктор глобальной статической переменной в разделяемой библиотеке не вызывается на dlclose MSVC уже запускает деструкторы на dlclose(),

7

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

Других решений пока нет …