LINUX.ORG.RU

Будет ли подлежащая библиотека проинициализирована ранее через __attribute__ ((constructor))

 


0

3

Привет!

Такой вопрос: есть такая вещь как __attribute__ ((constructor)). Предположим я использую его в инициализации библиотеки. Потом использую его в приложении, которое использует эту библиотеку. Я правильно понимаю, что библиотечный ((constructor)) будет вызван раньше приложенческого? Отвечаю на вопрос, зачем мне это нужно - мне надо вызвать функцию библиотеки в инициализаторе приложения, а эта функция работать без инициализатора библиотеки не будет.

Нужен официальный пруф.

Вопрос номер два. А будет это работать в более сложной цепочке? A.so (init A) <- B.so (init B, related on A) <- C.elf (init C, related on B)

Minimal Code Example:

mkdir -p /tmp/libtest && echo -e "#include <stdio.h>\n\nint target = 10;\n\nstatic void target_init(void) __attribute__ ((constructor));\n\nstatic void target_init(void)\n{\n    target = 50;\n}\n\nint target_return(void)\n{\n\n    return target;\n}\n" > /tmp/libtest/lib.c && echo -e "#include <stdio.h>\n\nextern int target_return(void);\n\nstatic void main_init(void) __attribute__ ((constructor));\n\nstatic void main_init(void)\n{\n    printf(\"main_init: %d\\\\n\", target_return())\n}\n\nint main(void)\n{\n    printf(\"main: %d\\\\n\", target_return());\n    return 0;\n}\n" > /tmp/libtest/main.c && gcc -fPIC -shared /tmp/libtest/lib.c -o /tmp/libtest/liblib.so && gcc main.c -o /tmp/libtest/main.elf -L. -llib && LD_LIBRARY_PATH=/tmp/libtest/ /tmp/libtest/main.elf
★★★★

Ты хочешь странного.

мне надо вызвать функцию библиотеки в инициализаторе приложения

Инициализатор приложения это main? Если не main, то почему бы операции делать не в нём?

ox55ff ★★★★★ ()
Ответ на: комментарий от ox55ff

Потому что я разрабатываю библиотеку, а не приложение.

Я, возможно, не совсем точно передал суть вопроса. Я пишу либу А, которой нужен ((constructor)). Я дергаю функцию из другой либы Б, у которой эта функция завязана на свой ((constructor)). Гарантируется ли, что конструктор либы Б вызовется раньше?

PPP328 ★★★★ ()
Ответ на: комментарий от PPP328

В сях не гарантируется. Просто напиши это в документации и проверяй на NULL.

Заметь что в языке нет ни конструкторов ни объектов.

Cactus64k ()
Последнее исправление: Cactus64k (всего исправлений: 2)

Minimal Code Example

За такое надо бить арматурой. Сложно было по-человечески сделать?

XMs ★★★★★ ()
Ответ на: комментарий от trashymichael

Ну если бы был другой механизм инициализации в библиотеке кроме втыкивания в каждую функцию if (!init) init_me()...

PPP328 ★★★★ ()

Нужен официальный пруф.

Там не густо в документации. Реализуется это вроде через _init/_fini, которые проходят по указателям и вызывают их. Они вызываются при загрузке/выгрузке библиотеки, так что всё должно работать в порядке зависимостей. В исходниках должно быть так, а дальше можно ещё в рассылке glibc спросить.

xaizek ★★★★★ ()

конструкторы(init) секции выстраиваются в порядке линкования либ, порядок может быть обратный в случае использования разных компиляторов, т.е. gcc/clang/итд

anonymous ()
Ответ на: комментарий от xaizek

Спасибо. Если начнет работать не совсем правильно (сейчас вроде правильно) - спрошу в рассылке.

PPP328 ★★★★ ()
Ответ на: комментарий от trashymichael

Ну как я и сказал, в каждой функции перед вызовом проверять была ли инициализация. Про падение производительности при этом рассказать?

PPP328 ★★★★ ()
Ответ на: комментарий от PPP328

ахаха, один вызов никакое не падение, сейчас бы в кк18 на вызовах экономить, ну сделай в момент подключения явную инициализацию и опиши порядок подключения, что такого?

trashymichael ★★★ ()
Ответ на: комментарий от trashymichael

один вызов никакое не падение

Алле, какой один вызов? Ваш метод требует в каждую функцию из 100 вставить if (!init). Знаете, сколько раз в секунду может дергаться set\get pixel если не юзается scanline? Несколько сотен миллионов.

PPP328 ★★★★ ()
Ответ на: комментарий от PPP328

тогда явная последовательная инициализация, все так делают, вон opengl и прочее надо инициализировать, тем более если вызывать «сотен миллионов» раз, нет буду нестандартные расширения, и ты так пишешь, не понимая даже что эти решения развертываются внутри по сути в такой же if/else, ведь магии не бывает и все повыше реализуется через что-то пониже, не думал об этом?

trashymichael ★★★ ()
Ответ на: комментарий от PPP328

лучше померяй потери от предложеных вначале конструкций, вот это реально интерестно, а один вызов даже на сотне миллионах итераций, не потеря, в gamedev это обсуждалось еще лет 10 назад, как возможная причина отказа от высокоуровневости в пользу быстродействия в игровых движках, и оказалось что нет выигрыша на современном железе, вызов ничего не стоит :P

trashymichael ★★★ ()
Ответ на: комментарий от trashymichael

раз, нет буду нестандартные расширения, и ты так пишешь, не понимая даже что эти решения развертываются внутри по сути в такой же if/else, ведь магии не бывает и все повыше реализуется через что-то пониже, не думал об этом?

Что это за поток сознания?

PPP328 ★★★★ ()
Ответ на: комментарий от EXL

Если целевых платформах имеется Android, то там есть один неприятный баг:

Это не сколько баг, сколько следствие, что этим хаком инициализируют ровно как ТС: библиотеку из из библиотеки. Но похоже ТСу голос разума не слышен. :(

vodz ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.