Вопрос или проблема
У меня довольно сложный проект на C++14, основанный на cmake, не так просто подготовить минимальный полный проверяемый пример. Используя Boost 1.73, я обнаружил проблему со связкой на этапе выполнения на Ubuntu 22.04/23.04. В частности, ldd возвращает что-то вроде этого:
libboost_regex.so.1.73.0 => not found
Другие библиотеки Boost (например, thread, filesystem) находятся успешно. Я обнаружил, что могу исправить проблему, явно добавив глобальный объект из библиотеки regex, например:
boost::basic_regex<char> fix_linker_issue("");
В то же время, объект, сконструированный по умолчанию, не помогает:
boost::basic_regex<char> doesnt_help;
Мог бы кто-нибудь объяснить мне причину, по которой это исправление работает?
Такой проблемы нет с более современной библиотекой Boost 1.84, скорее всего, потому что библиотека regex стала только заголовочной.
Ответ или решение
Решение проблемы компоновщика с явной инстанциацией объектов в C++
В вашем проекте на C++14, который использует CMake и библиотеку Boost 1.73, вы столкнулись с проблемой компоновки (linking) на стадии выполнения, где ldd
возвращает сообщение о том, что библиотека libboost_regex.so.1.73.0
не найдена. Это может быть вызвано тем, что компилятор не находит необходимых символов в динамической библиотеке при подключении. Давайте подробнее рассмотрим причину этой проблемы и специфику решения с явной инстанциацией.
Проблема с динамической компоновкой
Когда вы используете линкер для сборки проекта, он пытается определить, какие символы (например, функции или классы) используются в вашем коде и из каких библиотек они должны быть извлечены. Если какие-либо символы не могут быть найдены, то возникают ошибки на этапе линковки или выполнения. В вашем случае линкеры не могут обнаружить необходимые символы из библиотеки boost_regex
, возможно потому, что они не используются напрямую в вашем коде.
Явная инстанциация объектов
Вы упомянули, что добавление глобального объекта типа boost::basic_regex<char> fix_linker_issue("");
решает проблему линковки, тогда как просто объявление объекта boost::basic_regex<char> doesnt_help;
не помогает. Давайте разберем, почему это происходит.
-
Явная инстанциация: При создании объекта
fix_linker_issue
с аргументом (пустая строка""
) происходит явная инстанциация этой функции и всей соответствующей логики библиотекиboost_regex
. Это не только создает экземпляр объекта, но и заставляет линкер включить в итоговый бинарный файл все необходимые символы, связанные с его конструктором. -
Отсутствие вызова: Когда вы создаете объект
doesnt_help
без аргументов, возможно, компилятор не генерирует код для его конструктора, поскольку не видит дальнейшего использования объекта в коде. Это может привести к тому, что необходимые символы остаются "неиспользованными" и отбрасываются линкером.
Изменение в Boost 1.84
Как вы верно заметили, в более новых версиях Boost (1.84 и выше) библиотека regex
стала только заголовочной (header-only). Это означает, что вам больше не нужна отдельная динамическая библиотека libboost_regex.so
. Вместо этого, при подключении заголовков, все необходимые определения доступны вовремя компиляции, что решает проблему отсутствия символов и, как следствие, проблему линковки.
Рекомендации
-
Проверка путей библиотек: Убедитесь, что все необходимые библиотеки установлены и пути к ним правильно указаны в вашем CMake файле.
-
Обновление Boost: Рассмотрите возможность обновления до более новой версии Boost, чтобы использовать преимущества библиотек, ставших только заголовочными. Это не только упростит настройку, но и повысит производительность и удобство.
-
Контроль за использованием объектов: Если проблема с линковкой повторяется, старайтесь явно инстанцировать объекты из библиотек, которые могут не использоваться напрямую в вашем коде, чтобы предотвратить аналогичные проблемы в будущем.
Завершая, непосредственно работа с линкером является тонким процессом, который требует учета всех используемых символов в коде. Иногда, такие решения как явная инстанциация объектов могут стать временной мерой для решения проблем с компоновкой в C++.