Обнаружение проблем совместимости 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
несовместимость была основной причиной.