Каковы последствия ссылки на библиотеку, к которой вы не обращаетесь к функциям? - PullRequest
1 голос
/ 20 июня 2011

У меня есть файл make для программы, которая ссылается на libdl.so со следующей строкой -ldl. Нет никаких вызовов для dlopen или любой из связанных функций. Каков эффект ссылки на эту библиотеку таким образом, даже если вы не используете ни одну из функций?

Ответы [ 4 ]

4 голосов
/ 20 июня 2011

Вам придется прочитать документацию для вашего компоновщика. Начиная с info ld в моей системе Linux / ELF / GNU Binutils (выделение добавлено):

`--as-needed'
`--no-as-needed'
     This option affects ELF DT_NEEDED tags for dynamic libraries
     mentioned on the command line after the `--as-needed' option.
     <b>Normally the linker will add a DT_NEEDED tag for each dynamic
     library mentioned on the command line, regardless of whether the
     library is actually needed or not.</b>  `--as-needed' causes a
     DT_NEEDED tag to only be emitted for a library that satisfies an
     undefined symbol reference from a regular object file or, if the
     library is not found in the DT_NEEDED lists of other libraries
     linked up to that point, an undefined symbol reference from
     another dynamic library.  `--no-as-needed' restores the default
     behaviour.

Вы можете проверить себя, запустив ldd в тестовой программе. На простой тестовой программе я получаю:

    linux-vdso.so.1 =>  (0x00007fffd8305000)
    libc.so.6 => /lib/libc.so.6 (0x00007f646c669000)
    /lib/ld-linux-x86-64.so.2 (0x00007f646c9ca000)

Однако, если я свяжусь с -ldl, я получу это:

    linux-vdso.so.1 =>  (0x00007fff644f1000)
    libdl.so.2 => /lib/libdl.so.2 (0x00007fb9b1375000)
    libc.so.6 => /lib/libc.so.6 (0x00007fb9b1014000)
    /lib/ld-linux-x86-64.so.2 (0x00007fb9b1579000)

Хотя libdl не используется моей программой. Однако, если я запускаю GCC с -Wl,--as-needed, libdl не будет связан. Согласно моим тестам, это работает, только если в командной строке указан *1017* до -ldl.

Каковы эффекты? Это означает, что ваш двоичный файл не будет работать в системах без разделяемой библиотеки, даже если вы ее не используете. Это также означает, что ваш двоичный файл сломается, если вы обновите общую библиотеку и удалите старую. Это не имеет большого значения, потому что бинарная совместимость в любом случае имеет значение, но я не вижу причин не включать -Wl,--as-needed для проектов в целом.

1 голос
/ 20 июня 2011

Связывание с общей библиотекой отличается от связывания статической библиотеки. Основные различия были объяснены уже @Dietrich Epp, но есть еще одна важная деталь. Общие библиотеки определяют функции void _init() и void _fini(void), которые вызываются при загрузке / выгрузке общей библиотеки; если вы не определите их сами, компоновщик добавит заглушки по умолчанию.

Они также будут вызываться, если вы связываете свою программу с разделяемой библиотекой, но не ссылаетесь на какой-либо символ из библиотеки (и не добавляете флаг --as-required linker).

1 голос
/ 20 июня 2011

Я написал небольшое приложение, которое использует только STL. Он имеет размер 8275 байт без привязки к каким-либо конкретным библиотекам:

    linux-gate.so.1 =>  (0x00e1e000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x0015a000)
    libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x0044b000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00741000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00250000)
    /lib/ld-linux.so.2 (0x00a75000)

Теперь, когда я компилирую и связываю его с boost_thread, он увеличивается до 8290 байт :

    linux-gate.so.1 =>  (0x009d9000)
    libboost_thread.so.1.40.0 => /usr/lib/libboost_thread.so.1.40.0 (0x00e59000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x003a3000)
    libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x00bc5000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00f8a000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00110000)
    libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0x00bf0000)
    librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0x00dd8000)
    /lib/ld-linux.so.2 (0x00ba3000)

Обратите внимание, что в моем коде нет вызова функции для функций boost_thread. Тем не менее, boost_thread добавляется в любом случае как зависимость моего приложения (как вы можете видеть на выходе ldd ).

0 голосов
/ 20 июня 2011

Большинство компоновщиков просто пропускают неиспользуемые объекты из окончательного двоичного файла, точно так же, как если бы вы не связывались с библиотекой с самого начала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...