14.2 Взаимодействие ¶
В этом разделе перечислены различные трудности, возникающие при использовании GCC вместе с другими компиляторами или с ассемблерами, линковщиками, библиотеками и отладчиками на определенных системах.
- На многих платформах GCC поддерживает другой ABI для C++, чем другие компиляторы, поэтому объектные файлы, скомпилированные GCC, нельзя использовать с объектными файлами, сгенерированными другим компилятором C++.
Область, где это различие наиболее очевидно, — это преобразование имен. Использование различного преобразования имен является преднамеренным, чтобы защитить вас от более скрытых проблем. Компиляторы отличаются по многим внутренним деталям реализации C++, включая: как размещаются экземпляры классов, как реализовано множественное наследование и как обрабатываются виртуальные вызовы функций. Если бы кодировка имен была одинаковой, ваши программы могли бы связываться с библиотеками, предоставленными другими компиляторами, но программы затем аварийно завершались бы при запуске. Несовместимые библиотеки затем обнаруживаются во время линковки, а не во время выполнения.
- На некоторых системах BSD, включая некоторые версии Ultrix, использование профилирования приводит к тому, что статические деструкторы переменных (в настоящее время используются только в C++) не запускаются.
- На SPARC GCC выравнивает все значения типа
doubleна границе 8 байт, и ожидает, что каждоеdoubleтакже будет выровнено. Компилятор Sun обычно предоставляетdoubleзначением выравнивание на 8 байт, за исключением одного: аргументы функций типаdoubleмогут не быть выровнены.В результате, если функция, скомпилированная Sun CC, получает адрес аргумента типа
doubleи передает этот указатель типаdouble *функции, скомпилированной с GCC, обращение к указателю может вызвать фатальный сигнал.Один из способов решения этой проблемы — скомпилировать всю программу с помощью GCC. Другое решение — изменить функцию, скомпилированную с Sun CC, чтобы скопировать аргумент в локальную переменную; локальные переменные всегда правильно выравниваются. Третье решение — изменить функцию, которая использует указатель, чтобы обращаться к нему через следующую функцию
access_doubleвместо прямого использования ‘*’:inline double access_double (double *unaligned_ptr) { union d2i { double d; int i[2]; }; union d2i *p = (union d2i *) unaligned_ptr; union d2i u; u.i[0] = p->i[0]; u.i[1] = p->i[1]; return u.d; }Сохранение в указатель может быть выполнено аналогичным образом с использованием того же объединения.
- В Solaris функция
mallocв библиотеке libmalloc.a может выделять память, выровненную только по 4 байта. Поскольку GCC на SPARC предполагает, что double имеют выравнивание на 8 байт, это может привести к фатальному сигналу, если double хранятся в памяти, выделенной библиотекой libmalloc.a.Решение — не использовать библиотеку libmalloc.a. Используйте вместо этого
mallocи связанные функции из libc.a; они не имеют этой проблемы. - На машине HP PA ADB иногда не работает с функциями, скомпилированными с GCC. В частности, это не работает с функциями, использующими
allocaили массивами переменного размера. Это происходит потому, что GCC не генерирует дескрипторы разворачивания HP-UX для таких функций. Возможно даже, что их невозможно сгенерировать. - Отладка (-g) не поддерживается на машине HP PA, если вы не используете предварительные инструменты GNU.
- Получение адреса метки может генерировать ошибки от ассемблера HP-UX PA. GAS для PA не имеет этой проблемы.
- Использование параметров с плавающей точкой для косвенных вызовов статических функций не будет работать при использовании ассемблера HP. Просто нет способа для GCC указать, какие регистры содержат аргументы для статических функций при использовании ассемблера HP. GAS для PA не имеет этой проблемы.
- В крайне редких случаях, связанных с некоторыми очень большими функциями, вы можете получить ошибки от HP линковщика, жалующиеся на смещение безусловной ветки за пределами границ. Это раньше происходило чаще в предыдущих версиях GCC, но сейчас это крайне редко. Если вы столкнетесь с этим, можно обойти проблему, уменьшив размер вашей функции.
- Код, скомпилированный GCC, иногда генерирует предупреждения от ассемблера HP-UX вида:
(warning) Use of GR3 when frame >= 8192 may cause conflict.
Эти предупреждения безвредны и могут быть безопасно проигнорированы.
- В крайне редких случаях, связанных с некоторыми очень большими функциями, вы можете получить ошибки от AIX ассемблера, жалующиеся на слишком большое смещение. Если вы столкнетесь с этим, можно обойти проблему, уменьшив размер вашей функции.
- Библиотека libstdc++.a в GCC полагается на семантику динамического линковщика SVR4, которая объединяет глобальные символы между библиотеками и приложениями, что особенно необходимо для функциональности потоков C++. Это не является стандартным поведением общих библиотек и динамической линковки AIX. libstdc++.a построена в AIX с включённой «линковкой во время выполнения», чтобы объединение символов могло произойти. Для использования этой функции приложение, связанное с libstdc++.a, должно включать флаг -Wl,-brtl в строке линковки. G++ не может наложить это, так как этот параметр может вмешиваться в семантику программы пользователя, и пользователи могут не всегда использовать ‘g++’ для линковки своего приложения. Приложения не обязаны использовать флаг -Wl,-brtl в строке линковки — остальная часть библиотеки libstdc++.a, которая не зависит от семантики объединения символов, будет продолжать работать правильно.
- Приложение может вставить собственное определение функций для функций, вызываемых libstdc++.a с включённой «линковкой во время выполнения» в AIX. Для этого приложение должно быть связано с опцией «линковкой во время выполнения», и функции должны быть явно экспортированы приложением (-Wl,-brtl,-bE:exportfile).
- AIX на RS/6000 предоставляет поддержку (NLS) для сред за пределами США. Компиляторы и ассемблеры используют NLS для поддержки представлений локали специфичных объектов, включая числа с плавающей точкой (‘.’ против ‘,’ для разделения десятичных дробей). Были сообщения о проблемах, когда библиотека, связанная с GCC, не производит те же форматы чисел с плавающей точкой, что и ассемблер. Если у вас возникла такая проблема, установите переменную среды
LANGв ‘C’ или ‘En_US’. - Даже если вы укажете -fdollars-in-identifiers, вы не сможете успешно использовать ‘$’ в идентификаторах на RS/6000 из-за ограничения в ассемблере IBM. GAS поддерживает эти идентификаторы.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/gcc/Interoperation.html