Как поймать неумышленное функциональное межрасположение?

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

Пример, данный в книге, следующий:

my_source.c

mktemp() { ... }

main() {
  mktemp();
  getwd();
}

libc

mktemp(){ ... }
getwd(){ ...; mktemp(); ... }

Согласно книге, что происходит в main() это mktemp() (функция стандартной библиотеки для C), вставляется реализацией в my_source.c. Хотя имея main() назовите мою реализацию mktemp() предназначенное поведение, имея getwd() (другая библиотечная функция C), также называют мою реализацию mktemp() не.

По-видимому, этим примером была реальная ошибка, которая существовала в версии SunOS 4.0.3's lpr. Книга продолжает объяснять, что фиксация должна была добавить ключевое слово static к определению mktemp() в my_source.c; хотя менять имя в целом должно было решить эту проблему также.

Эта глава оставляет меня с некоторыми неразрешенными вопросами, что я надеюсь Вы, парни могли ответить:

  1. GCC имеет способ предупредить о функциональном вмешательстве? Мы, конечно, никогда не предназначаем на этом случае, и я хотел бы знать об этом, если это делает.
  2. Если наша группа программного обеспечения принимает практику помещения ключевого слова static перед всеми функциями, что мы не хотим быть подвергнутыми?
  3. Вмешательство может произойти с функциями, представленными статическими библиотеками?

Спасибо за справку.

Править

Я должен отметить, что мой вопрос только нацелен на вставку по функциям стандартной библиотеки для C, но также и функциям, содержавшимся в других библиотеках, возможно, третьей стороне, возможно, созданные внутренний. По существу я хочу поймать любой экземпляр межрасположения независимо от того, где вставленная функция находится.

6
задан SiegeX 6 May 2010 в 20:37
поделиться

5 ответов

Похоже, что вы хотите, чтобы инструменты обнаружили конфликты имен в функциях - т.е. вы не хотите, чтобы имена ваших внешне доступных функций случайно имели одинаковые имена и поэтому "перекрывали" или скрывали функции с одинаковыми именами в библиотеке.

Недавно на SO был вопрос, связанный с этой проблемой: Linking Libraries with Duplicate Class Names using GCC

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

.
1
ответ дан 17 December 2019 в 07:01
поделиться

Чисто формально описываемое вами взаимное расположение является прямое нарушение правил определения языка C (правило ODR на языке C ++). Любой достойный компилятор должен либо обнаруживать эти ситуации, либо предоставлять возможности для их обнаружения. Просто незаконно определять более одной функции с одним и тем же именем на языке C, независимо от того, где эти функции определены (Стандартная библиотека, другая пользовательская библиотека и т. Д.)

Я понимаю, что многие платформы предоставляют средства для настройки [стандартного ] поведения библиотеки, определяя некоторые стандартные функции как слабые символы . Хотя это действительно полезная функция, я считаю, что компиляторы должны по-прежнему предоставлять пользователю средства для обеспечения стандартной диагностики (желательно для каждой функции или каждой библиотеки).

Итак, опять же, вам не следует беспокоиться о взаимном расположении, если в ваших библиотеках нет слабых символов. Если вы это сделаете (или если вы подозреваете, что это так), вы должны проконсультироваться с документацией вашего компилятора, чтобы узнать, предлагает ли он вам средства для проверки слабого разрешения символов.

В GCC, например, вы можете отключить функциональность слабых символов с помощью -fno-weak , но это в основном убивает все, что связано со слабыми символами, что не всегда желательно.

1
ответ дан 17 December 2019 в 07:01
поделиться

Если к функции не нужно обращаться за пределами файла C, в котором она находится, то да, я бы рекомендовал сделать функцию статической.

Одна вещь, которую вы можете сделать, чтобы избежать этого, - использовать редактор с настраиваемой подсветкой синтаксиса. Я лично использую SciTE, и я настроил его на отображение всех имен функций стандартной библиотеки красным цветом. Таким образом, легко заметить, если я повторно использую имя, которое не должен использовать (однако компилятор ничего не навязывает).

0
ответ дан 17 December 2019 в 07:01
поделиться

Относительно легко написать сценарий, который запускает nm -o на всех ваших .o файлах и библиотеках и проверяет, определено ли внешнее имя как в вашей программе, так и в библиотеке. Это всего лишь одна из многих разумных услуг, которые компоновщик Unix не предоставляет, потому что он застрял в 1974 году, просматривая по одному файлу за раз. (Попробуйте расположить библиотеки в неправильном порядке и посмотрите, получите ли вы полезное сообщение об ошибке!)

0
ответ дан 17 December 2019 в 07:01
поделиться

Это действительно проблема компоновщика.

Когда вы компилируете кучу исходных файлов C, компилятор создает объектный файл для каждого из них. Каждый файл .o будет содержать список общедоступных функций в этом модуле, а также список функций, которые вызываются кодом в модуле, но фактически не определены там, то есть функции, которые этот модуль ожидает от какой-либо библиотеки.

Когда вы связываете группу файлов .o вместе, чтобы сделать исполняемый файл, компоновщик должен разрешить все эти отсутствующие ссылки. Это момент, когда может произойти вставка. Если есть неразрешенные ссылки на функцию с именем "mktemp" и несколько библиотек предоставляют общедоступную функцию с этим именем, какую версию следует использовать? На этот вопрос нет простого ответа, и да, могут произойти странные вещи, если будет выбран неправильный вариант

. Так что да, в C хорошей идеей будет «статизировать» все, если вам действительно не нужно использовать это из других исходных файлов. Фактически, во многих других языках это поведение по умолчанию, и вы должны пометить вещи как «общедоступные», если хотите, чтобы они были доступны извне.

2
ответ дан 17 December 2019 в 07:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: