Почему порядок, в котором связаны библиотеки, иногда вызывает ошибки в GCC?

Почему порядок, в котором библиотеки связаны, иногда вызывает ошибки в GCC?

418
задан Konrad Rudolph 26 June 2019 в 12:31
поделиться

4 ответа

Я видел это много, часть нашей ссылки модулей сверх 100 библиотеки нашего кода плюс система & третья сторона освобождает.

В зависимости от различных компоновщиков HP/Intel/GCC/SUN/SGI/IBM/etc можно получить неразрешенные функции/переменные и т.д. на некоторых платформах, необходимо перечислить библиотеки дважды.

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

, Как только Вы наталкиваетесь на решение, документируют его так, следующий разработчик не должен разрабатывать его снова.

Мой старый лектор раньше говорил, " высокая связность & слабая связь ", it’s, все еще верный сегодня.

3
ответ дан darrenp 26 June 2019 в 12:31
поделиться

GNU ld компоновщик является так называемым умным компоновщиком. Это будет отслеживать функции, используемые путем предшествования статическим библиотекам, постоянно выбрасывания тех функций, которые не используются из его таблиц поиска. Результат состоит в том, что при соединении статической библиотеки слишком рано, тогда функции в той библиотеке больше не доступны статическим библиотекам позже строка ссылки.

типичный компоновщик UNIX работает слева направо, таким образом, помещает все Ваши зависимые библиотеки слева и тех, которые удовлетворяют те зависимости справа от строки ссылки. Можно найти, что некоторые библиотеки зависят от других, в то время как одновременно другие библиотеки зависят от них. Это - то, где это сложно. Когда дело доходит до циклических ссылок зафиксируйте свой код!

96
ответ дан casualcoder 26 June 2019 в 12:31
поделиться
  • 1
    @atpatil11, Apko bhi shukria, паритет mein Сааб nehi hoon bhai, sirf Heera kafi hai. – The Alpha 22 July 2013 в 10:19

(См. историю на этом ответе для получения более тщательно продуманного текста, но я теперь думаю, что для читателя легче видеть реальные командные строки).

<час>

Общие файлы, совместно использованные всеми ниже команд

$ cat a.cpp
extern int a;
int main() {
  return a;
}

$ cat b.cpp
extern int b;
int a = b;

$ cat d.cpp
int b;

Соединение со статическими библиотеками

$ g++ -c b.cpp -o b.o
$ ar cr libb.a b.o
$ g++ -c d.cpp -o d.o
$ ar cr libd.a d.o

$ g++ -L. -ld -lb a.cpp # wrong order
$ g++ -L. -lb -ld a.cpp # wrong order
$ g++ a.cpp -L. -ld -lb # wrong order
$ g++ a.cpp -L. -lb -ld # right order

, компоновщик ищет слева направо и отмечает неразрешенные символы, когда это идет. Если библиотека разрешает символ, она берет объектные файлы той библиотеки для разрешения символа (b.o из libb.a в этом случае).

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

, Если статическая библиотека зависит от другой библиотеки, но другая библиотека снова зависит от бывшей библиотеки, существует цикл. Можно разрешить это путем включения циклически зависимых библиотек -( и -), такой как -( -la -lb -) (Вы, возможно, должны выйти из parens, такой как -\( и -\)). Компоновщик тогда ищет те включенный lib многократно, чтобы гарантировать, что циклически повторяющиеся зависимости разрешены. С другой стороны, можно определить библиотеки многократно, таким образом, каждый друг перед другом: -la -lb -la.

Соединение с динамическими библиотеками

$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -L. -ld -o libb.so # specifies its dependency!

$ g++ -L. -lb a.cpp # wrong order (works on some distributions)
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong order
$ g++ -Wl,--as-needed a.cpp -L. -lb # right order

Это - то же здесь - библиотеки должны следовать за объектными файлами программы. Различие здесь по сравнению со статическими библиотеками - то, что Вы не должны заботиться о зависимостях библиотек друг против друга, потому что динамические библиотеки разбираются в самих своих зависимостях .

Некоторые недавние дистрибутивы, по-видимому, значение по умолчанию к использованию --as-needed флаг компоновщика, который осуществляет это объектные файлы программы, прибывает перед динамическими библиотеками. Если тот флаг будет передан, компоновщик не свяжется с библиотеками, которые не на самом деле необходимы исполняемому файлу (и это обнаруживает это слева направо). Мое недавнее archlinux распределение не использует этот флаг по умолчанию, таким образом, это не дало ошибку для того, чтобы не выполнять правильный приказ.

Это не корректно для исключения зависимости [1 111] против [1 112] при создании первого. Вы будете обязаны определять библиотеку, когда для соединения a тогда, но a действительно не нужно целое число b само, таким образом, это не должно быть сделано заботиться [приблизительно 1 116] о собственных зависимостях.

Вот пример последствий, если Вы избегаете определять зависимости для [1 117]

$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -o libb.so # wrong (but links)

$ g++ -L. -lb a.cpp # wrong, as above
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong, as above
$ g++ a.cpp -L. -lb # wrong, missing libd.so
$ g++ a.cpp -L. -ld -lb # wrong order (works on some distributions)
$ g++ -Wl,--as-needed a.cpp -L. -ld -lb # wrong order (like static libs)
$ g++ -Wl,--as-needed a.cpp -L. -lb -ld # "right"

, Если Вы теперь изучаете, какие зависимости двоичный файл имеет, Вы отмечаете, что сам двоичный файл зависит также от [1 118], не всего libb, как это должно. Двоичный файл должен будет быть повторно связан, если libb позже будет зависеть от другой библиотеки, если Вы делаете это этот путь. И если кто-то еще загрузится libb использование dlopen во времени выполнения (думайте о загружающихся плагинах динамично), то вызов перестанет работать также. Так "right" действительно должен быть wrong также.

528
ответ дан Jonathan Leffler 26 June 2019 в 12:31
поделиться

Порядок связей, безусловно, имеет значение, по крайней мере, на некоторых платформах. Я видел сбои для приложений, связанных с библиотеками в неправильном порядке (где неправильный означает A, связанный перед B, но B зависит от A).

2
ответ дан 22 November 2019 в 23:18
поделиться
Другие вопросы по тегам:

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