Обработка глобальных конструкторов и деструкторов

При использовании глобальных, то есть не внутри функции, объектов, компилятор и компоновщик формируют массивы указателей на конструкторы и деструкторы (при необходимости). Массивы называются .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)();

Аналогично обрабатывается и массив деструкторов.