Динамическая линковка C++ на AIX
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;
}
Но это не программирование, а ерзанье.
Оригинальный пост | Disclaimer