Вынудите GCC уведомить о неопределенных ссылках в общих библиотеках

У меня есть общая библиотека, которая связана с другим совместно использованная библиотека (третьего лица). Моя общая библиотека затем загружается с помощью dlopen в моем приложении. Все это хорошо работает (предположение, что файлы находятся в надлежащем пути и т.д.).

Теперь, проблема состоит в том, что я не должен даже указывать для соединения против совместно использованной библиотеки третьего лица, когда я связываю свою библиотеку. GCC принимают его, не сообщая об ошибках о неопределенных ссылках. Так, вопрос; как я могу вынудить GCC уведомить меня о неопределенных ссылках?

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

Т.е. следующее сделано:

g++ -fPIC -shared -o libb.so b.o 
g++ -fPIC -shared -o liba.so a.o
g++ -o a.exe a.cpp 

Где вторая строка НЕ выделяет ошибку, и третья строка жалуется на неопределенную ссылку.

Пример кода:

a.h:

class a
{
public:
    void foobar();
};

a.cpp:

#include "a.h"
#include "b.h"

void a::foobar()
{
    b myB;
    myB.foobar();
}

int main()
{
    a myA; myA.foobar();
}

b.h:

class b
{
public:
    void foobar();
};

b.cpp:

#include "b.h"

void b::foobar()
{
}
48
задан P Shved 1 March 2010 в 06:23
поделиться

3 ответа

-Wl, - no-undefined параметр компоновщика может использоваться при построении разделяемой библиотеки, неопределенные символы будут отображаться как ошибки компоновщика.

g ++ -shared -Wl, -soname, libmylib.so.5 -Wl, - no-undefined -o libmylib.so.1.1 mylib.o -lthirdpartylib

50
ответ дан 7 November 2019 в 12:37
поделиться

После дополнительных исследований я понял, как это работает. Есть два варианта компоновщика для управления неопределенными символами разделяемых библиотек:

Первый - - no-undefined . Он сообщает о неразрешенных символах, которые не разрешаются сразу на этапе связывания. Если символ не найден в совместно используемой библиотеке, с которой связана ссылка, либо вручную (с переключателем -l ), либо автоматически ( libgcc_s , среда выполнения C ++; libc , среда выполнения C ; ld-linux - **. So , утилит динамического компоновщика) выбрано, - no-undefined сообщает об ошибке. Это ключ, который нужен вопрошающему.

Есть еще один ключ, - no-allow-shlib-undefined (описание которого также предполагает - no-undefined ). Он проверяет, удовлетворены ли определения в разделяемых библиотеках , с которыми вы связываете вашу разделяемую библиотеку с . В случае, показанном в этом разделе, от этого ключа мало пользы, но он может быть полезен. Однако у него есть свои препятствия.

Справочная страница дает некоторое объяснение, почему это не по умолчанию:

   --allow-shlib-undefined
   --no-allow-shlib-undefined
       Allows  (the  default)  or  disallows  undefined  symbols  in  shared
       libraries (It is meant, in shared libraries _linked_against_, not the
       one we're creating!--Pavel Shved). This switch is similar to --no-un-
       defined except  that it determines  the  behaviour when the undefined
       symbols are in a shared library rather than a regular object file. It
       does not  affect  how  undefined  symbols in regular object files are
       handled.

       The  reason  that  --allow-shlib-undefined is the default is that the
       shared library being specified at link time may not be  the  same  as
       the one that is available at load time, so the symbols might actually
       be resolvable at load time.  Plus there are some systems,  (eg  BeOS)
       where  undefined  symbols in shared libraries is normal.  (The kernel
       patches them at load time to select which function is most  appropri-
       ate for the current architecture.  This is used for example to dynam-
       ically select an appropriate memset function).  Apparently it is also
       normal for HPPA shared libraries to have undefined symbols.

Дело в том, что сказанное выше также верно, например, для систем Linux, где некоторые из внутренних процедур разделяемой библиотеки реализованы в ld-linux.so , динамический загрузчик (это как исполняемая, так и разделяемая библиотека). Если вы каким-то образом не свяжете его, вы получите что-то вроде этого:

/lib64/libc.so.6: undefined reference to `_dl_argv@GLIBC_PRIVATE'
/lib64/libc.so.6: undefined reference to `_rtld_global_ro@GLIBC_PRIVATE'
/usr/lib64/gcc/x86_64-suse-linux/4.3/libstdc++.so: undefined reference to `__tls_get_addr@GLIBC_2.3'
/lib64/libc.so.6: undefined reference to `_rtld_global@GLIBC_PRIVATE'
/lib64/libc.so.6: undefined reference to `__libc_enable_secure@GLIBC_PRIVATE'

Это неопределенные ссылки из загрузчика, ld-linux.so . Он зависит от платформы (например, в моей системе правильный загрузчик /lib64/ld-linux-x86-64.so ). Вы можете связать загрузчик со своей библиотекой и проверить даже сложные ссылки, показанные выше:

g++ -fPIC -shared -o liba.so a.o -Wl,--no-allow-shlib-undefined  /lib64/ld-linux-x86-64.so.2
18
ответ дан 7 November 2019 в 12:37
поделиться

Вы не можете заставить ld (это то, что работает gcc) обратить внимание на библиотеку, которая нет в ссылке. Вы можете отключить RTLD_LAZY, чтобы получать агрессивные отчеты, и вы можете добавить модульный тест, который запускается сразу после ссылки, просто чтобы устранить эти проблемы.

1
ответ дан 7 November 2019 в 12:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: