Программа не может найти правильную версию glibc/libstdc++, хотя она была статически слинкована

Я пытаюсь статически связать свою программу с glibc, потому что версия glibc на целевой машине практически непредсказуема. Я использовал флаги компоновщика -static-libgcc и -static-libstdc++, и все работало нормально. Исполняемый файл большой, но я могу с ним жить. К сожалению, когда я запускаю свой исполняемый файл на целевой машине (в приведенном ниже примере он называется «mytest»), я получаю следующую ошибку:

./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by libboost_log.so.1.53.0)
./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by libboost_log.so.1.53.0)
./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by libboost_log.so.1.53.0)
./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by libboost_date_time.so.1.53.0)
./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by libboost_thread.so.1.53.0)

Если я делаю «строки» на моем тесте, это дает мне

$ strings mytest | grep GLIBC
GLIBC_2.9
GLIBC_2.7
GLIBC_2.8
GLIBC_2.3.2
GLIBC_2.2.5
GLIBCXX_3.4.15
GLIBCXX_3.4.11
GLIBCXX_3.4.14
GLIBCXX_3.4.9
GLIBCXX_3.4

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

Спасибо!


person svetlana    schedule 27.04.2013    source источник


Ответы (2)


Я пытаюсь статически связать свою программу с glibc, потому что версия glibc на целевой машине практически непредсказуема. Я использовал флаги компоновщика -static-libgcc и -static-libstdc++, и все работало нормально.

Это не повлияло на версию glibc (libc), которая отличается от libgcc и libstdc++. С этими флагами вы по-прежнему создаете динамически подключаемый исполняемый файл, который, ожидается, не будет работать в старом дистрибутиве.

Вы можете связать свой исполняемый файл с флагом -static, и это должно дать вам полностью статический исполняемый файл.

Обновление:

После повторного чтения вашего вопроса; ваша проблема не связана с glibc. Ваша проблема в том, что вы связываетесь с libboost_log.so, который сам зависит от libstdc++.so.6.

Тогда ответ заключается в том, чтобы связать с libboost*.a вместо libboost*.so. Вы можете попытаться добиться этого следующим образом:

g++ $(OBJS) -static-libgcc -static-libstdc++ -Wl,-Bstatic -lboost_log ... \
  -Wl,-Bdynamic

(очень важно иметь в конце -Wl,-Bdynamic.)

person Employed Russian    schedule 27.04.2013
comment
Большое спасибо. К сожалению, я не могу слинковать все статически, потому что тогда моя библиотека pthread не работает. По какой-то причине он работает нормально, только если он связан динамически. - person svetlana; 27.04.2013
comment
@svetlana libpthread является частью glibc. Если вы не можете связать его статически, то у вас не может быть полностью статического исполняемого файла, а это означает, что ваш исполняемый файл никогда не будет работать в более старой системе (это просто не поддерживается). Статическая компоновка действительно работает для многопоточных программ в целом, поэтому вам нужно либо выяснить, почему она не работает в вашем конкретном случае, либо отказаться от всей этой идеи. - person Employed Russian; 27.04.2013
comment
А, это интересно. Я никогда не использовал флаги -B, но это может сработать. Еще раз спасибо :) - person svetlana; 28.04.2013
comment
Хорошо, я попробовал ваше предложение. Теперь я получаю ./mytest: ошибка поиска символа: /home/sveta/mytest/lib/libstdc++.so.6: неопределенный символ: _ZGVNSt8numpunctIcE2idE, версия GLIBCXX_3.4 ЕСЛИ я пробую readelf -Ws mytest, я вижу символ. Излишне говорить, что он присутствует в libstdc++.so.6. Я запутался... Вернемся к первоначальному вопросу: почему он не использует статическую версию из исполняемого файла??? - person svetlana; 28.04.2013

Связывание с -static-libgcc и -static-libstdc++ будет работать только для этих библиотек. Похоже, вы также связываетесь с библиотеками повышения (вероятно, динамически), которые затем связываются с libgcc и libstdc++.

Попробуйте запустить следующее:

ldd mytest

Он должен показывать «не динамический исполняемый файл». Если он показывает что-то еще, это означает, что он динамически связан с другими библиотеками. Это не всегда работает так просто, но попробуйте добавить -static в строку компиляции, чтобы позаботиться об оставшихся библиотеках.

person Alec Bennett    schedule 27.04.2013