Обнаружение проблем совместимости ABI с GCC

Недавно я потратил довольно много времени на поиск проблемы, которая, как оказалось, была вызвана компиляцией библиотеки с -D_GLIBCXX_DEBUG (который говорит libstdC++ использовать отладочную версию стандартной библиотеки с дополнительными проверками), но компилирует клиентскую программу без. Это вызвало проблему совместимости ABI.

Есть ли способ, которым я могу автоматически обнаруживать подобные проблемы с GCC? Visual Studio предоставляет detect_mismatch Прагма, которая, я думаю, послужила бы этой цели, но я не знаю ни одного эквивалента GCC. GCC что-то делает с встраиванием имени символа (например, GLIBCXX_3.4.9), и я могу представить схемы, которые могли бы вызвать ошибку компоновки из-за неопределенного символа, если соответствующий символ (например, mylib_debug_stl) не было, но я могу придумать только один способ использовать этот символ.

В качестве альтернативы, как другие люди избегают этой проблемы? Создать проверенную версию библиотеки под другим именем или что-то в этом роде?

2 ответа

Решение

Есть ли способ, которым я могу автоматически обнаруживать подобные проблемы с GCC?

Только компоновщик может определить, ссылаетесь ли вы на несовместимый код, а не на компилятор.

Альтернативный линкер, gold, может обнаружить некоторые проблемы с --detect-odr-violations вариант.

В качестве альтернативы, как другие люди избегают этой проблемы? Создать проверенную версию библиотеки под другим именем или что-то в этом роде?

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

Я редко пользуюсь -D_GLIBCXX_DEBUG во всяком случае, я чаще делаю что-то вроде:

#if 0
# include <debug/vector>
namespace my_class_stl = __gnu_debug;
#else
#include <vector>
namespace my_class_stl = std;
#endif

struct my_class
{
  typedef my_class_stl::vector<int> container;
  typedef container::iterator iterator;
  // ...
};

Затем я изменяю условие препроцессора, когда хочу использовать вектор режима отладки для этого конкретного класса, не затрагивая каждый контейнер в программе. Поскольку изменение включает запись в файл (и, соответственно, обновление его временной метки), все, что зависит от этого заголовка, будет восстановлено makeи есть два разных типа, std::vector<int> а также __gnu_debug::vector<int>, которые имеют разные символы и не могут быть перепутаны компоновщиком.

Просто определяя _GLIBCXX_DEBUG не приводит к перестройке всех зависимостей и незаметно изменяет определение std::vector глобально, вместо того, чтобы менять конкретные контейнеры на другой тип с другим именем, __gnu_debug::vector

Оказалось, что это вызвано компиляцией библиотеки с -D_GLIBCXX_DEBUG (которая указывает libstdC++ использовать отладочную версию стандартной библиотеки с дополнительными проверками), но компиляцией клиентской программы без.

Это явный libsdc++ цель разработки режима отладки для поддержки такой конфигурации, и я несколько сомневаюсь, что это было реальной причиной вашей проблемы.

Возможно, проблема исчезла после того, как вы перестроили библиотеку без -D_GLIBCXX_DEBUG, но это не доказывает, что ABI несовместимость была основной причиной.

Другие вопросы по тегам