15.2 Взаимодействие
В этом разделе перечислены различные трудности, возникающие при использовании GCC вместе с другими компиляторами или с ассемблерами, компоновщиками, библиотеками и отладчиками в некоторых системах.
- На многих платформах GCC поддерживает ABI для C++, отличный от ABI других компиляторов, поэтому объектные файлы, скомпилированные 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. При использовании ассемблера HP GCC просто не может указать, в каких регистрах находятся аргументы статических функций. У 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 с включённой функцией «runtime-linking», благодаря чему возможно объединение символов. Чтобы воспользоваться этой функцией, приложение, компонуемое с libstdc++.a, должно содержать флаг -Wl,-brtl в командной строке компоновки. G++ не может добавлять этот флаг принудительно, поскольку параметр может повлиять на семантику программы пользователя, а пользователи не всегда используют ‘g++’ для компоновки своих приложений. Приложениям не обязательно указывать флаг -Wl,-brtl в командной строке компоновки: остальные части библиотеки libstdc++.a, не зависящие от семантики объединения символов, продолжат работать правильно.
- Приложение может подменить собственными определениями функции, вызываемые библиотекой libstdc++.a с включённой функцией «runtime-linking» в AIX. Для этого приложение необходимо скомпоновать с параметром «runtime-linking», а функции должны быть явно экспортированы приложением (-Wl,-brtl,-bE:exportfile).
- AIX на RS/6000 поддерживает (NLS) среды за пределами США. Компиляторы и ассемблеры используют NLS для поддержки локализованных представлений различных объектов, включая числа с плавающей точкой (‘.’ или ‘,’ в качестве разделителя десятичной дроби). Сообщалось о проблемах, когда библиотека, скомпонованная с GCC, формирует форматы чисел с плавающей точкой, отличающиеся от форматов, принимаемых ассемблером. Если у вас возникла такая проблема, установите переменную среды
LANGв значение ‘C’ или ‘En_US’. - Даже если вы укажете -fdollars-in-identifiers, из-за ограничения в ассемблере IBM вы не сможете успешно использовать ‘$’ в идентификаторах на RS/6000. GAS поддерживает такие идентификаторы.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Interoperation.html