Есть ли значимое различие между автономными и размещенными реализациями?

Вопрос, который у меня есть, в основном связан с шестым разделом четвертым.

Две формы соответствующей реализации являются размещенными и автономными. Соответствующая размещенная реализация должна принимать любую строго соответствующую программу.

Как я понимаю, это типичная среда приложения с файловыми системами, выделенной памятью и потоками...

Соответствующая автономная реализация должна принимать любую строго соответствующую программу, в которой использование функций, указанных в разделе библиотеки (пункт 7), ограничено содержимым стандартных заголовков. <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, а также <stdnoreturn.h>,

... и это типичное ядро ​​и / или встроенная минимальная среда, в которой нет стандартных файловых систем, выделенной памяти или потоков (среди прочего).

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

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

  • fopen, fgets а также malloc может вернуться NULL
  • fprintf, fscanf, fputc а также fgetc может вернуться EOF
  • thrd_create может вернуться thrd_error (указывая, что "запрос не может быть выполнен")

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

4 ответа

В цитированном параграфе это уже хорошо сказано.

Размещенная среда выполнения также является автономной, но не наоборот. Компилятор должен предоставлять только автономную реализацию. Например, gcc, строго говоря, является только автономной, так как стандартная библиотека не включена. Однако предполагается, что он доступен при компиляции для размещенной среды (по умолчанию), при условии, что библиотека доступна в системе (например, glibc). Смотрите здесь

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

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

Так что, если здание для голого металла, вы всегда должны пройти -ffreestanding,

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

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

5.1.2.1 далее заявляет, что "Любые библиотечные средства, доступные для автономной программы, кроме минимального набора, требуемого пунктом 4, определяются реализацией". Это поддерживает мое заявление. Sidenote: также не требует main() в качестве точки входа в программу.

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

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

Программа, строго соответствующая (т. Е. Любому) стандарту, максимально переносима.

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

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

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

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

В целом, реализации, предназначенные для автономного использования, будут использоваться на платформах, которые не смогут эффективно обрабатывать размещенную реализацию. В то время как Стандарт предъявляет некоторые требования, выходящие за рамки того, что было бы практичным на некоторых из меньших платформ C, некоторые почти согласующиеся реализации C могут быть весьма полезны для процессоров с достаточным объемом памяти для хранения 256 инструкций и 16-байтовых переменных. Если что-то вроде гаджета цифрового кухонного термометра / таймера не имеет файловой системы или консоли, почему оно должно тратить память на такие вещи, как дескрипторы для stdout?

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

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

      sizeof(char) == sizeof(int);
sizeof(size_t) < sizeof(int signed);
// SIZE_MAX < INT_MAX

Размещенная среда явно требует

      sizeof(char) < sizeof(int);
// (int)EOF != (char)EOF;
sizeof(int unsigned) <= sizeof(size_t);
// UINT_MAX <= SIZE_MAX

Если sizeof(char) == sizeof(int), EOFне определено.

Если argc > SIZE_MAX, вы не можете позвонить main.

Другие вопросы по тегам