Заставить GCC уведомлять о неопределенных ссылках в общих библиотеках - PullRequest
46 голосов
/ 01 марта 2010

У меня есть общая библиотека, которая связана с другой (сторонней) общей библиотекой. Моя общая библиотека загружается с использованием 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 

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

Пример кода:

хиджра:

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()
{
}

Ответы [ 3 ]

45 голосов
/ 01 марта 2010

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

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

17 голосов
/ 01 марта 2010

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

Первый - --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
1 голос
/ 01 марта 2010

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

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