AIX мне всегда нравился своим особо изощренным отношением к линковке.
Итак, рассмотрим пример (система AIX 5.3).
Файл alib.cpp
компилируем как динамическую библиотеку.
struct A { A() { value_ = 123; } int value_; }; A a = A(); extern "C" int value() { return a.value_; }
В этой библиотеке создается статический объект класса А
, и значение его поля возвращается функцией value()
.
Компилируем:
xlC -o alib.so -qrtti=all -qmkshrobj=-100 -G -brtl -bnolibpath alib.cpp
xlC
- это компилятор С++ на AIX.
Далее, файл main.c
. Это головной модуль на С
, который вызывает функцию value()
.
extern int value(); int main() { return value(); }
Этот модуль вызывает value()
, и значение становится кодом возврата процесса.
Компилируем:
xlc -c -o main.o main.c
xlc
(маленькая “с” на конце) - это компилятор С на AIX.
Линкуем, используя компилятор С, запускаем и печатаем код возврата ($?
)
xlc -o main main.o alib.so && LIBPATH=.:$LIBPATH ./main ; echo $?
Результат на экране:
0
Интересно?! Почему не ожидаемое 123?
Теперь линкуем, используя компилятор “С++”, запускаем и печатаем код возврата:
xlC -o main main.o alib.so && LIBPATH=.:$LIBPATH ./main ; echo $?
Результат на экране:
123
Мораль: на AIX, при динамической линковке библиотек, чтобы правильно работала статическая инициализация на С++, надо принудительно линковать конечный бинарь в режиме С++ (как бы это странно не звучало). Иначе конструкторы статических объектов вызваны не будут, и их инициализация будет произведена не ДО функции main()
, а непонятно когда.
Можно принудительно заставить таки систему вызвать конструкторы статических объектов, написав что-то вроде:
#include <dlfcn.h> static int module_initialised = 0; static void ManualInitilizationForStatics() { if (module_initialised) return; dlopen("blah.so", RTLD_NOW); module_initialised = 1; }
Но это не программирование, а ерзанье.