stringtranslate.com

Стандартная библиотека C

Стандартная библиотека C или libc — это стандартная библиотека для языка программирования C , как указано в стандарте ISO C. [1] Начиная с оригинального стандарта ANSI C , она была разработана одновременно со спецификацией библиотеки C POSIX , которая является ее надмножеством. [2] [3] Поскольку ANSI C был принят Международной организацией по стандартизации , [4] стандартная библиотека C также называется библиотекой ISO C.

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

Интерфейс прикладного программирования (API)

Заголовочные файлы

Интерфейс прикладного программирования (API) стандартной библиотеки C объявлен в ряде заголовочных файлов . Каждый заголовочный файл содержит одно или несколько объявлений функций, определений типов данных и макросов.

После длительного периода стабильности три новых файла заголовков ( iso646.h, wchar.h, и wctype.h) были добавлены в Нормативное дополнение 1 (NA1), дополнение к стандарту C, ратифицированному в 1995 году. Еще шесть файлов заголовков ( complex.h, fenv.h, inttypes.h, stdbool.h, stdint.hи tgmath.h) были добавлены в C99 , пересмотренный вариант стандарта C, опубликованный в 1999 году, и еще пять файлов ( stdalign.h, stdatomic.h, stdnoreturn.h, threads.h, и uchar.h) — в C11 в 2011 году. Всего теперь имеется 29 файлов заголовков:

Три заголовочных файла ( complex.h, stdatomic.h, и threads.h) представляют собой условные функции, поддержка которых не является обязательной для реализаций.

Стандарт POSIX добавил несколько нестандартных заголовков C для специфичных для Unix функций. Многие из них нашли свой путь в другие архитектуры. Примерами являются fcntl.hи unistd.h. Ряд других групп используют другие нестандартные заголовки – библиотека GNU C имеет alloca.h, а OpenVMS имеет va_count()функцию.

Документация

В Unix-подобных системах официальная документация API предоставляется в виде man-страниц . В большинстве систем man-страницы по стандартным библиотечным функциям находятся в разделе 3; раздел 7 может содержать несколько более общих страниц по базовым концепциям (например, man 7 math_errorв Linux ).

Реализации

Unix-подобные системы обычно имеют библиотеку C в форме разделяемой библиотеки , но заголовочные файлы (и набор инструментов компилятора) могут отсутствовать в установке, поэтому разработка на языке C может быть невозможна. Библиотека C считается частью операционной системы в Unix-подобных системах; в дополнение к функциям, указанным в стандарте C, она включает другие функции, которые являются частью API операционной системы, например, функции, указанные в стандарте POSIX . Функции библиотеки C, включая функции стандарта ISO C, широко используются программами и рассматриваются как не только реализация чего-либо на языке C, но и фактическая часть интерфейса операционной системы. Unix-подобные операционные системы, как правило, не могут функционировать, если библиотека C стерта. Это справедливо для приложений, которые динамически, а не статически связаны. Кроме того, само ядро ​​(по крайней мере, в случае Linux) работает независимо от каких-либо библиотек.

В Microsoft Windows основные системные динамические библиотеки ( DLL ) предоставляют реализацию стандартной библиотеки C для компилятора Microsoft Visual C++ v6.0; стандартная библиотека C для более новых версий компилятора Microsoft Visual C++ предоставляется каждым компилятором индивидуально, а также в виде распространяемых пакетов. Скомпилированные приложения, написанные на C, либо статически связаны с библиотекой C, либо связаны с динамической версией библиотеки, которая поставляется с этими приложениями, а не должны присутствовать в целевых системах. Функции в библиотеке C компилятора не считаются интерфейсами для Microsoft Windows.

Существует множество реализаций библиотеки C, поставляемых как с различными операционными системами, так и с компиляторами C. Вот некоторые из популярных реализаций:

Встроенные функции компилятора

Некоторые компиляторы (например, GCC [7] ) предоставляют встроенные версии многих функций стандартной библиотеки C; то есть реализации функций записываются в скомпилированный объектный файл , и программа вызывает встроенные версии вместо функций в общем объектном файле библиотеки C. Это снижает накладные расходы на вызов функций, особенно если вызовы функций заменяются встроенными вариантами, и допускает другие формы оптимизации (поскольку компилятор знает характеристики потока управления встроенных вариантов), но может вызвать путаницу при отладке (например, встроенные версии нельзя заменить инструментированными вариантами).

Однако встроенные функции должны вести себя как обычные функции в соответствии с ISO C. Главное следствие заключается в том, что программа должна иметь возможность создавать указатель на эти функции, беря их адрес, и вызывать функцию с помощью этого указателя. Если два указателя на одну и ту же функцию выводятся в двух разных единицах трансляции в программе, эти два указателя должны сравниваться как равные; то есть адрес получается путем разрешения имени функции, которая имеет внешнюю (общепрограммную) связь.

Связывание, libm

В FreeBSD [8] и glibc [9] некоторые функции, такие как sin(), не связаны по умолчанию и вместо этого объединены в математическую библиотеку libm . Если какая-либо из них используется, компоновщику должна быть задана директива -lm. POSIX требует, чтобы компилятор c99 поддерживал -lm, и чтобы функции, объявленные в заголовках math.h, complex.hи fenv.hбыли доступны для связывания, если -lmуказано , но не указывает, связаны ли функции по умолчанию. [10] musl удовлетворяет этому требованию, помещая все в одну библиотеку libc и предоставляя пустую libm. [11]

Обнаружение

Согласно стандарту C, макрос __STDC_HOSTED__должен быть определен как 1, если реализация размещена. Размещенная реализация имеет все заголовки, указанные стандартом C. Реализация также может быть автономной, что означает, что эти заголовки не будут присутствовать. Если реализация является автономной , она должна быть определена __STDC_HOSTED__как 0 .

Проблемы и пути их решения

Уязвимости переполнения буфера

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

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

Комитет ISO C опубликовал Технические отчеты TR 24731-1 [12] и работает над TR 24731-2 [13], чтобы предложить принятие некоторых функций с проверкой границ и автоматическим распределением буфера, соответственно. Первый встретил суровую критику с некоторой похвалой, [14] [15], а последний получил неоднозначную реакцию.

Несмотря на опасения, TR 24731-1 был интегрирован в стандарт языка C в приложении K к стандарту ISO/IEC 9899:2011 (C11) ( Интерфейсы проверки границ ) и приблизительно реализован в библиотеке среды выполнения C/++ (CRT) Microsoft для платформ Win32 и Win64.

(По умолчанию компиляторы Microsoft Visual Studio C и C++ выдают предупреждения при использовании старых, «небезопасных» функций. Однако реализация TR 24731-1 от Microsoft неявно несовместима как с TR 24731-1, так и с Приложением K, [16] поэтому в переносимых проектах эти предупреждения обычно отключаются или игнорируются. Их можно отключить напрямую, выполнив

#pragma предупреждение(отключить: 4996)

до/около места вызова, о котором идет речь, или косвенно, путем выдачи

#define _CRT_SECURE_NO_WARNINGS 1

перед включением любых заголовков. [17] Параметр командной строки /D_CRT_NO_SECURE_WARNINGS=1должен иметь тот же эффект, что и этот #define.)

Проблемы с потоками, уязвимость к условиям гонки

Процедура strerror()критикуется за то, что она небезопасна для потоков и уязвима к условиям гонки .

Обработка ошибок

Обработка ошибок функций в стандартной библиотеке C не является последовательной и иногда запутанной. Согласно странице руководства Linux math_error, «текущая ситуация (версия 2.8) в glibc запутанная. Большинство (но не все) функций вызывают исключения при ошибках. Некоторые также устанавливают errno . Несколько функций устанавливают errno , но не вызывают исключения. Очень немногие функции делают ни то, ни другое». [18]

Стандартизация

Исходный язык C не предоставлял встроенных функций, таких как операции ввода-вывода, в отличие от традиционных языков, таких как COBOL и Fortran . [ требуется ссылка ] Со временем сообщества пользователей C поделились идеями и реализациями того, что сейчас называется стандартными библиотеками C. Многие из этих идей в конечном итоге были включены в определение стандартизированного языка C.

И Unix , и C были созданы в Bell Laboratories компании AT&T в конце 1960-х и начале 1970-х годов. В 1970-х годах язык C становился все более популярным. Многие университеты и организации начали создавать собственные варианты языка для своих проектов. К началу 1980-х годов стали очевидны проблемы совместимости между различными реализациями C. В 1983 году Американский национальный институт стандартов (ANSI) сформировал комитет для установления стандартной спецификации C, известной как « ANSI C ». Эта работа завершилась созданием так называемого стандарта C89 в 1989 году. Частью получившегося стандарта был набор программных библиотек, называемых стандартной библиотекой ANSI C.

Стандартная библиотека POSIX

POSIX , а также SUS , определяют ряд процедур, которые должны быть доступны сверх тех, что в базовой стандартной библиотеке C. Спецификация POSIX включает заголовочные файлы, среди прочего, для многопоточности , работы в сети и регулярных выражений . Они часто реализуются вместе с функциональностью стандартной библиотеки C с различной степенью близости. Например, glibc реализует такие функции, как forkв libc.so, но до того, как NPTL был объединен с glibc, он представлял собой отдельную библиотеку со своим собственным аргументом флага компоновщика. Часто эта функциональность, указанная в POSIX, будет рассматриваться как часть библиотеки; базовая библиотека C может быть идентифицирована как библиотека ANSI или ISO C.

BSD-библиотека

BSD libc — это надмножество стандартной библиотеки POSIX, поддерживаемое библиотеками C, включенными в операционные системы BSD, такие как FreeBSD , NetBSD , OpenBSD и macOS . BSD libc имеет некоторые расширения, которые не определены в исходном стандарте, многие из которых впервые появились в выпуске 4.4BSD 1994 года (первом, который был в значительной степени разработан после выпуска первого стандарта в 1989 году). Некоторые из расширений BSD libc:

Стандартная библиотека C на других языках

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

С++

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

Для обратной/перекрестной совместимости с C и достандартным C++ доступ к функциям можно осуществлять в глобальном пространстве имен ( :: ), после указания имени стандартного заголовка C, как в C. [40] Таким образом, программа C++98#include

#include <stdio.h> int main () { return :: puts ( "Привет, мир!" ) == EOF ; }      

должна демонстрировать (по-видимому) идентичное поведение программе C95

#include <stdio.h> int main ( void ) { return puts ( "Привет, мир!" ) == EOF ; }      

Начиная с C++98 функции C также доступны в пространстве имен ::std (например, C  printf как C++  ::std::printf , atoi как ::std::atoi , feof как ::std::feof ) путем включения заголовка вместо соответствующего заголовка C. Например, <cstdio> заменяет <stdio.h> и <cmath> вместо <math.h> ; обратите внимание на отсутствие расширения .h в именах заголовков C++.<chdrname><hdrname.h>

Таким образом, эквивалентная (как правило, предпочтительная) программа на C++≥98 двум вышеприведенным программам выглядит следующим образом:

#include <cstdio> int main () { return std :: puts ( "Привет, мир" ) == EOF ; }      

Можно сделать объявление выше или внутри main, чтобы автоматически применить префикс :: std :: , хотя обычно считается плохой практикой использовать его глобально в заголовках, поскольку это загрязняет глобальное пространство имен. [41]using namespace ::std

Некоторые из версий заголовков C++≥98 отсутствуют; например, C≥11 <stdnoreturn.h> и <threads.h> не имеют аналогов в C++. [42]

Другие сводятся к заполнителям, таким как (до C++20 ) <ciso646> для C95 <iso646.h> , все необходимые макросы которого отображаются как ключевые слова в C++98. Синтаксические конструкции, специфичные для C, обычно не поддерживаются, даже если их заголовок поддерживается. [43]

Несколько заголовков C существуют в первую очередь для совместимости с C++, и они, как правило, почти пусты в C++. Например, C99 – 17 <stdbool.h> требует только

#define bool _Bool #define false 0 #define true 1 #define __bool_true_false_are_defined 1

для имитации поддержки ключевых слов C++98 bool , false и true в C. C++11 требует <stdbool.h> и <cstdbool> для совместимости, но все, что им нужно определить, это __bool_true_false_are_defined . C23 отменяет старое ключевое слово _Bool в пользу новых, эквивалентных C++98 ключевых слов bool , false и true , поэтому заголовки C≥23 и C++≥11 <stdbool.h> / <cstdbool> полностью эквивалентны. (В частности, C23 не требует макроса __STDC_VERSION_BOOL_H__ для <stdbool.h> .)

Доступ к функциям библиотеки C через пространство имен ::std и имена заголовков C++≥98 предпочтительнее, где это возможно. Чтобы поощрить принятие, C++98 делает устаревшими имена заголовков C ( *.h ), поэтому возможно, что использование заголовков совместимости с C приведет к тому, что особенно строгий препроцессор C++98–20 выдаст диагностику какого-либо рода. Однако C++23 (что необычно) делает эти заголовки устаревшими, поэтому более новые реализации/режимы C++ не должны жаловаться, если их специально не попросили об этом. [44]


Другие языки используют аналогичный подход, помещая функции/процедуры совместимости с C в общее пространство имен; к ним относятся D , Perl и Ruby .


Питон

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

В более общем плане Python  2. x определяет встроенные файловые объекты как «реализованные с использованием пакета stdio языка C [46] », и часто ссылается на поведение стандартной библиотеки C; ожидается, что доступные операции ( open, read, write, и т. д.) будут иметь то же поведение, что и соответствующие функции C ( fopen, fread, fwrite, и т. д.).

Однако спецификация Python 3 значительно меньше опирается на специфику языка C, чем Python 2 .

Ржавчина

Rust предлагает crate libc , который позволяет использовать различные стандартные библиотечные функции C (и другие) и определения типов. [47]

Сравнение со стандартными библиотеками других языков

Стандартная библиотека C невелика по сравнению со стандартными библиотеками некоторых других языков. Библиотека C предоставляет базовый набор математических функций, манипуляции строками, преобразования типов , а также файловый и консольный ввод-вывод. Она не включает стандартный набор « типов контейнеров », как библиотека стандартных шаблонов C++ , не говоря уже о полных наборах инструментов графического пользовательского интерфейса (GUI), сетевых инструментах и ​​изобилии других функций, которые Java и .NET Framework предоставляют в качестве стандарта. Главное преимущество небольшой стандартной библиотеки заключается в том, что предоставление рабочей среды ISO C намного проще, чем с другими языками, и, следовательно, перенос C на новую платформу сравнительно прост.

Смотрите также

Примечания

  1. ^ Червь Морриса , использующий известную уязвимость, gets()был создан еще в 1988 году.
  2. ^ в стандартной библиотеке C вычисление длины строки и поиск конца строки имеют линейную временную сложность и неэффективны при многократном использовании для одних и тех же или связанных строк

Ссылки

  1. ^ ISO / IEC (2018). ISO/IEC 9899:2018(E): Языки программирования - C §7
  2. ^ "Библиотека GNU C – Введение". gnu.org . Получено 2013-12-05 .
  3. ^ "Разница между стандартной библиотекой C и библиотекой C POSIX". stackoverflow.com . 2012 . Получено 2015-03-04 .
  4. ^ "Стандарты C". C: Стандарты C. Keil . Получено 24 ноября 2011 г.
  5. ^ "Re: Поддерживает ли Newlib процессоры без mmu?". Cygwin.com. 23 марта 2006 г. Архивировано из оригинала 22 ноября 2008 г. Получено 28 октября 2011 г.
  6. ^ "musl libc". Etalabs.net . Получено 28 октября 2011 г. .
  7. ^ Другие встроенные функции, предоставляемые GCC, Руководство GCC
  8. ^ "Компиляция с помощью cc" . Получено 2013-03-02 .
  9. ^ Ваймер, Флориан. "c - Для каких функций предназначена библиотека libm?". Stack Overflow . Получено 24 февраля 2021 г. .
  10. ^ "c99 - компилировать стандартные программы на языке C". The Open Group Base Specifications Issue 7, издание 2018 года . The Open Group . Получено 24 февраля 2021 года .
  11. ^ "musl FAQ". www.musl-libc.org . Получено 24 февраля 2021 г. .
  12. ^ "ISO/IEC TR 24731-1: Расширения библиотеки C, Часть I: Интерфейсы проверки границ" (PDF) . open-std.org. 2007-03-28 . Получено 2014-03-13 .
  13. ^ "ISO/IEC WDTR 24731-2: Расширения библиотеки C, Часть II: Динамические функции распределения" (PDF) . open-std.org. 2008-08-10 . Получено 2014-03-13 .
  14. ^ Используете ли вы «безопасные» функции TR 24731 в своем коде на языке C? - Stack overflow
  15. ^ "Обзор группы Austin по ISO/IEC WDTR 24731" . Получено 28 октября 2011 г.
  16. ^ "Опыт работы с Приложением K — Интерфейсы проверки границ" . Получено 9 октября 2024 г. .
  17. ^ "Функции безопасности в CRT — устранение предупреждений об устаревании" . Получено 9 октября 2024 г. .
  18. ^ "math_error - обнаружение ошибок в математических функциях". man7.org . 2008-08-11 . Получено 2014-03-13 .
  19. ^ "дерево". Man.freebsd.org . 2007-12-27 . Получено 2013-08-25 .
  20. ^ "Справочник суперпользователя BSD: /OpenBSD/sys/sys/tree.h". bxr.su .
  21. ^ "queue". Man.freebsd.org . 2011-05-13 . Получено 2013-08-25 .
  22. ^ "Справочник суперпользователя BSD: /OpenBSD/sys/sys/queue.h". bxr.su .
  23. ^ "fgetln". Man.freebsd.org . 1994-04-19 . Получено 2013-08-25 .
  24. ^ "Справочник суперпользователя BSD: /OpenBSD/lib/libc/stdio/fgetln.c". bxr.su .
  25. ^ "Ссылка на BSD суперпользователя: /OpenBSD/include/stdio.h". bxr.su .
  26. ^ "fts". Man.freebsd.org . 2012-03-18 . Получено 2013-08-25 .
  27. ^ "Ссылка на BSD суперпользователя: /OpenBSD/include/fts.h". bxr.su .
  28. ^ "db". Man.freebsd.org . 2010-09-10 . Получено 2013-08-25 .
  29. ^ "Ссылка на BSD суперпользователя: /OpenBSD/include/db.h". bxr.su .
  30. ^ Миллер, Тодд К. и Тео де Раадт. strlcpy и strlcat — согласованное, безопасное копирование и конкатенация строк. Труды Ежегодной технической конференции USENIX 1999 г., 6–11 июня 1999 г., стр. 175–178.
  31. ^ "Справочник суперпользователя BSD: /OpenBSD/lib/libc/string/strlcat.c". bxr.su .
  32. ^ "Справочник суперпользователя BSD: /OpenBSD/lib/libc/string/strlcpy.c". bxr.su .
  33. ^ "Справочник суперпользователя BSD: /OpenBSD/lib/libc/string/strncat.c". bxr.su .
  34. ^ "Справочник суперпользователя BSD: /OpenBSD/lib/libc/string/strncpy.c". bxr.su .
  35. ^ "err". Man.freebsd.org . 2012-03-29 . Получено 2013-08-25 .
  36. ^ "Ссылка на BSD суперпользователя: /OpenBSD/include/err.h". bxr.su .
  37. ^ "vis(3)". Man.FreeBSD.org . Получено 14 сентября 2013 г. .
  38. ^ "Справочник суперпользователя BSD: /OpenBSD/lib/libc/gen/vis.c". bxr.su .
  39. ^ "Справочник суперпользователя BSD: /OpenBSD/include/vis.h". bxr.su .
  40. ^ Заголовки стандартной библиотеки C++ — Заголовки совместимости с C , получено 9 октября 2024 г.
  41. ^ Kieras, David (15 февраля 2015 г.). «Использование «using»: как использовать пространство имен std» (PDF) . Раздаточные материалы EECS381 . Кафедра EECS, Мичиганский университет. Архивировано (PDF) из оригинала 2022-12-24 . Получено 9 октября 2024 г. . Один оператор в одном заголовочном файле в сложном проекте может испортить управление пространством имен для всего проекта. Поэтому никаких операторов верхнего уровня [ ] в заголовочном файле!using namespace std;using namespace
  42. ^ "Заголовки стандартной библиотеки C++ — Неподдерживаемые заголовки C" . Получено 9 октября 2024 г. .
  43. ^ "Заголовки стандартной библиотеки C++ — Бессмысленные заголовки C" . Получено 9 октября 2024 г. .
  44. ^ "Заголовки стандартной библиотеки C++ — Заголовки совместимости с C" . Получено 9 октября 2024 г. .
  45. ^ "ctypes — библиотека внешних функций для Python". docs.python.com . Получено 9 октября 2024 г. .
  46. ^ "The Python Standard Library, §5.9: File Objects" . Получено 9 октября 2024 г. File Objects реализованы с использованием пакета stdio языка C и могут быть созданы с помощью встроенной функции.open()
  47. ^ "Crate libc". Rust Crates . Получено 9 октября 2024 г.

Дальнейшее чтение

Внешние ссылки