Насколько широко поддерживается прагма и преодолевается ли проблема использования атрибута gcc? - PullRequest
6 голосов
/ 24 февраля 2012

Я только что обнаружил директиву #pragma weak в GCC:

6.57.9 Слабые прагмы

Для совместимости с SVR4, GCC поддерживает набор директив #pragma для объявления символовбыть слабым и определять слабые псевдонимы.

#pragma weak symbol

Эта прагма объявляет символ слабым, как если бы объявление имело атрибут с тем же именем.Прагма может появиться до или после объявления символа.Это не ошибка для символа, который никогда не будет определен вообще.

#pragma weak symbol1 = symbol2

Эта прагма объявляет символ 1 слабым псевдонимом символа 2.Будет ошибкой, если символ2 не определен в текущей единице перевода.

http://gcc.gnu.org/onlinedocs/gcc/Weak-Pragmas.html

Несмотря на то, что разработчики GCC, как правило, не любят #pragma и поощряютчтобы вы использовали __attribute__ вместо всех видов вещей, которые могли бы быть прагмами, я склонен полагать, что #pragma weak может на самом деле превосходить подход на основе атрибутов, который выглядит следующим образом:

extern __typeof(old_name) new_name __attribute__(weak, alias("old_name"))

Помимо уродливости требования __typeof (или требования, чтобы вы знали тип и указывали его явно, даже если это действительно сложный тип функции), самая большая проблема подхода на основе атрибутов заключается в том, что "old_name" необходимо передатьgcc в виде строки , которая будет вставлена ​​буквально в сгенерированную сборку.Это проблематично, потому что разные системы имеют разные характеристики распределения имен (наиболее популярным является префикс подчеркивания на всех именах символов C или вообще ничего не делает), и для передачи правильной строки в атрибут alias необходимо знатьсоглашение о распределении имен системы, для которой вы создаете, что на самом деле не является знанием, относящимся к библиотеке уровня приложения, где могут быть полезны слабые псевдонимы.

Синтаксис #pragma weak new_name = old_name, кажется, позволяет избежать этой проблемы при обработкеоба имени на уровне компилятора, где t может манипулировать ими обоими надлежащим образом, если я не ошибаюсь.

Итак, после завершения всех предварительных экзаменов мои настоящие вопросы: Я ошибаюсь из-за того, что #pragma weakэто преимущество «переносимости»? и Все ли современные компиляторы в Unix-подобных системах (gcc, pcc, tinycc, icc, llvm / clang и т. д.) все еще поддерживают традиционный SVR4 #pragma weak?

Мне известен следующий подобный вопрос, но он не выглядит так же, как и ответНе можете удовлетворительно ответить на мой вопрос:

Насколько мобильна слабая связь?#pragma слабый my_symbol

1 Ответ

4 голосов
/ 27 февраля 2012

Ни "#pragma слабый", ни __attribute__ не являются частью стандарта C, поэтому, строго говоря, они не являются переносимыми. Некоторые компиляторы C стремятся быть совместимыми с большинством расширений GCC к стандарту C, другие - нет.

Вообще говоря, если вы уже на уровне разговоров о слабых символах и слабых псевдонимах, вы, вероятно, уже достигли той точки, когда вы можете писать код, который надежно переносится между компиляторами. Даже ваша цепочка инструментов станет проблемой здесь (включая особенно компоновщик) - я не думаю, что вы можете положиться на что-либо без тщательного тестирования.

Отредактировано, чтобы добавить: оригинальный постер, прокомментированный ниже, спрашивающий, прагматически ли, #pragma не менее переносим, ​​чем __attribute __.

Мой собственный опыт таков: приятно иметь возможность скрывать все подобные вещи внутри макросов или другого сгенерированного кода, чтобы облегчить переносимость. __attribute__ легче скрыть в заголовочном файле переносимости. Например, по крайней мере одно из ядер BSD имеет файл cdefs.h, который использует __attribute__ внутри макроса, чтобы централизовать способ выполнения слабых определений во всей кодовой базе, чтобы упростить изменения в новых компиляторах. #pragma сложнее использовать таким образом. Такой макрос также может скрывать разницу между различными именами с помощью оператора вставки CPP ("##" и т. Д.)

Пример такого использования см .: http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/cdefs.h?rev=1.89.6.1&content-type=text/x-cvsweb-markup

...