При использовании глобальных, то есть не внутри функции, объектов, компилятор и компоновщик формируют массивы указателей на конструкторы и деструкторы (при необходимости). Массивы называются .init_ar и .fini_ar .
Поскольку идентификаторы в С++ не могут начинаться с точки, эти идентификаторы недоступны напрямую.
Чтобы получить к ним доступ, приходится воспользоваться скриптом для компоновщика:
...
.init_array : ALIGN(0x10) {
PROVIDE_HIDDEN(__init_array_begin = .);
*(.init_array) ;
PROVIDE_HIDDEN(__init_array_end = .);
}
.fini_array : ALIGN(0x10) {
PROVIDE_HIDDEN(__fini_array_begin = .);
*(.fini_array) ;
PROVIDE_HIDDEN(__fini_array_end = .);
}
...
Теперь можно использовать идентификаторы С в коде
using func_t = void(*)(void);
extern "C" {
extern func_t __init_array_begin[];
extern func_t __init_array_end[];
}
Необходимо определять именно как массивы, иначе вместо использования адреса конструктора как адреса функции, будет попытка вызова кода конструктора как адреса функции.
Обработка массивов прямолинейная, с помощью цикла:
for(auto _array=__init_array_begin; _array != __init_array_end; _array++)
(*_array)();
Аналогично обрабатывается и массив деструкторов.