Есть много возможных причин этого. В результате вы получаете доступ к объектам, еще не созданным (поскольку порядок создания объектов в разных единицах перевода не определен), что, на мой взгляд, вполне вероятно в этом случае, и приводит к ошибке в вашей среде сборки.
Чтобы вызвать собственную функцию перед другой функцией конструктора, у вас есть атрибут constructor (priority)
, описанный здесь . GCC сохраняет приоритет для каждого раздела ввода конструктора файлов. И это связывает их в порядке приоритетов. В скрипте компоновщика моей системы Linux этот код выглядит следующим образом (выведите его с помощью ld -verbose
):
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
Вы хотите присвоить ему низкий приоритет, чтобы он выполнялся раньше, чем другие зарегистрированные функции ctor с более высоким номером приоритета. Однако, судя по всему, сначала не будут выполняться конструкторы, не имеющие номера. Не совсем уверен. Лучше всего попробовать. Если вы хотите, чтобы ваша функция вызывалась еще до _do_global_ctors_aux, вы должны выпустить оригинальную функцию _init
, которая обычно выполняется, когда ваша программа загружается загрузчиком ELF (смотрите параметр -init
в ld). Прошло некоторое время с тех пор, как я с ней связался, но я помню, что он должен был сделать некоторые интимные детали инициализации, поэтому я не стал бы пытаться заменить его. Попробуйте использовать атрибут конструктора, с которым я связан. Однако будьте очень осторожны. Возможно, ваш код будет выполнен до того, как будут созданы другие важные объекты, такие как cout
.
Обновление : я сделал тест, и он фактически выполняет функции ctor в обратном порядке. Таким образом, функции ctor, которые связаны первыми, выполняются позже. Этот код находится в crtstuff.c исходного кода gcc:
func_ptr *p;
for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
(*p) ();
Я сделал небольшой тест:
void dothat() { }
struct f {
f() { dothat(); }
} f_;
void doit() __attribute__((constructor (0)));
void doit() { }
int main() { }
Связывание с --print-map
дает, помимо прочего, такой вывод:
.ctors 0x080494f4 0x10
*crtbegin.o(.ctors)
.ctors 0x080494f4 0x4 /usr/lib/gcc/i686-pc-linux-gnu/4.3.2/crtbegin.o
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
.ctors 0x080494f8 0x4 /tmp/ccyzWBjs.o
*(SORT(.ctors.*))
.ctors.65535 0x080494fc 0x4 /tmp/ccyzWBjs.o
*(.ctors)
.ctors 0x08049500 0x4 /usr/lib/gcc/i686-pc-linux-gnu/4.3.2/crtend.o
Обратите внимание, как .ctors.65535
является разделом, который мы неявно создали нашим приоритетом атрибута 0
. Теперь, если вы отдадите этому приоритету, gcc предупреждает, и это совершенно верно: p
test.cpp: 7: предупреждение: приоритеты конструктора от 0 до 100 зарезервированы для реализации
Я проверил его, взломав doit
и dothat
, и он назвал их в порядке, который мы ожидаем. Веселись!