Ответ 1
Стандарт С++ требует, чтобы деструкторы вызывались для глобальных объектов, когда программа выходит в противоположном порядке построения. Большинство реализаций справились с этим, вызвав подпрограмму atexit библиотеки C для регистрации деструкторов. Это проблематично, потому что в стандарте 1999 C только требуется, чтобы реализация поддерживала 32 зарегистрированных функции, хотя большинство реализаций поддерживают многие другие. Более важно то, что в большинстве реализаций нет возможности удалить DSO из исполняемого образа программы, вызвав dlclose до завершения программы.
Эта проблема рассматривается в более поздних версиях GCC, включая стандартную библиотеку Cic и компоновщик. В принципе, деструкторы С++ должны быть зарегистрированы с помощью функции __cxa_atexit
вместо atexit
(3).
Подробную техническую информацию о __cxa_atexit
см. в спецификации Itanium С++ ABI.
Из вашего вопроса непонятно, какая версия gcc, компоновщика и стандартной библиотеки C вы используете. Кроме того, код, который вы предоставили, не соответствует стандарту POSIX, поскольку не определены макросы RTDL_NOW
или RTDL_LOCAL
. Они RTLD_NOW
и RTLD_LOCAL
(см. dlopen).
Если ваша стандартная библиотека C не поддерживает __cxa_atexit
, вам может потребоваться ее отключить, указав флаг -fno-use-cxa-atexit
gcc:
-fuse-CXA-atexit
Зарегистрировать деструкторы для объектов со статическим хранилищем длительность с __cxa_ atexit функции, а не atexit функция. Этот параметр необходим для полностью совместимая с стандартами обработка статические деструкторы, но будут работать только если ваша библиотека C поддерживает __cxa_atexit.
Но это может привести к проблеме, когда деструкторы вызываются в другом порядке или вообще не вызываются. Поэтому лучшим решением в случае сломанной поддержки __cxa_atexit
или вообще без поддержки является не использование статических объектов с деструкторами в ваших общих библиотеках.