У меня 2 библиотеки: test.1
и test.2
. Обе библиотеки содержат одну глобальную функцию extern «C»void f();
с различными реализациями (всего лишь cout
для теста).Одинаковые символы в разных библиотеках и порядок связи
я сделал следующий тест:
Тест 1 Динамическая компоновка:
Если добавить libtest.1.so
и затем libtest.2.so
в Makefile исполняемого файла, а затем вызвать f();
в main
, libtest.1.so->f()
называется.
Если изменить порядок в Makefile, libtest.2.so->f()
называется
Тест 2 Статическое связывание:
Абсолютно то же самое происходит со статическими библиотеками
Тест 3 Динамическая загрузка
Как библиотека ручная загрузка, все работает так, как ожидалось.
Я ожидал ошибку для нескольких определений, которых явно не было.
Кроме того, это не нарушает правило с одним определением, так как ситуация отличается.
Это также не зависимость-ад (не то, что это связано с этим вообще), ни сшивание облом ..
Таким образом, чем это? Неопределенное поведение? Неопределенное поведение? Или это действительно зависит от порядка привязки?
И есть ли способ легко обнаружить такие ситуации?
Похожие вопросы:
dlopen vs linking overhead
What is the difference between dynamic linking and dynamic loading
Is there a downside to using -Bsymbolic-functions?
Why does the order in which libraries are linked sometimes cause errors in GCC?
linking two shared libraries with some of the same symbols
EDIT я сделал еще два испытания, которые подтверждают это UB:
Я добавил вторую функцию void g()
в test.1
и НЕ в test.2
.
Использование динамической компоновки и .so
libs, то же самое происходит - f
вызывается таким же образом, g
также исполняется (как и ожидалось).
Но используя статические ссылки в настоящее время изменяет вещи: если test.1
является перед темtest.2
, нет никаких ошибок, обе функции от test.1
называется.
Но когда порядок изменен, возникает ошибка «нескольких определений».
Понятно, что «нет необходимости в диагностике» (см. Ответ @ MarkB), но «странно», что иногда происходит ошибка, иногда - нет.
В любом случае, ответ довольно ясен и объясняет все выше - UB.
/Я считаю, что стандартом, над которым вы должны проверять это поведение, является стандарт ELF, а не стандарт C++. – ninjalj