C-Standardbibliothek - C standard library

Die C-Standardbibliothek oder libc ist die Standardbibliothek für die Programmiersprache C , wie sie im ISO-C- Standard spezifiziert ist . Ausgehend vom ursprünglichen ANSI-C- Standard wurde es gleichzeitig mit der POSIX-Spezifikation der C-Bibliothek entwickelt , die eine Obermenge davon ist. Da ANSI C von der International Organization for Standardization übernommen wurde , wird die C-Standardbibliothek auch ISO-C-Bibliothek genannt .

Die C - Standardbibliothek bietet Makros , Typ Definitionen und Funktionen für Aufgaben wie String - Handling, mathematische Berechnungen, Input / Output - Verarbeitung, Speicherverwaltung und mehrere andere Betriebssystemdienste.

Programmierschnittstelle

Header-Dateien

Die Anwendungsprogrammierschnittstelle (API) der C-Standardbibliothek ist in mehreren Header-Dateien deklariert . Jede Headerdatei enthält eine oder mehrere Funktionsdeklarationen, Datentypdefinitionen und Makros.

Nach einer langen Zeit der Stabilität wurden mit Normative Addendum 1 (NA1), einer Ergänzung zum 1995 ratifizierten C-Standard , drei neue Header-Dateien ( iso646.h, wchar.h, und wctype.h) hinzugefügt . Sechs weitere Header-Dateien ( , , , , , und ) wurden hinzugefügt mit C99 , einer Revision C - Standard im Jahr 1999 veröffentlicht wird , und fünf weitere Dateien ( , , , , und ) mit C11 im Jahr 2011. insgesamt gibt es nun 29 Header - Dateien: complex.hfenv.hinttypes.hstdbool.hstdint.htgmath.hstdalign.hstdatomic.hstdnoreturn.hthreads.huchar.h

Name Von Beschreibung
<assert.h> Enthält das Assert- Makro, das verwendet wird, um logische Fehler und andere Arten von Fehlern beim Debuggen von Versionen eines Programms zu erkennen.
<complex.h> C99 Eine Reihe von Funktionen zum Manipulieren komplexer Zahlen .
<ctype.h> Definiert eine Reihe von Funktionen, die verwendet werden, um Zeichen nach ihrem Typ zu klassifizieren oder zwischen Groß- und Kleinschreibung unabhängig vom verwendeten Zeichensatz zu konvertieren (normalerweise ASCII oder eine seiner Erweiterungen, obwohl auch Implementierungen mit EBCDIC bekannt sind).
<errno.h> Zum Testen von Fehlercodes, die von Bibliotheksfunktionen gemeldet werden.
<fenv.h> C99 Definiert eine Reihe von Funktionen zum Steuern der Gleitkommaumgebung .
<float.h> Definiert Makrokonstanten , die die implementierungsspezifischen Eigenschaften der Gleitkommabibliothek angeben.
<inttypes.h> C99 Definiert Integertypen mit exakter Breite .
<iso646.h> NA1 Definiert mehrere Makros , die alternative Möglichkeiten zum Ausdrücken mehrerer Standardtoken implementieren. Zur Programmierung in ISO 646- Varianten-Zeichensätzen.
<limits.h> Definiert Makrokonstanten , die die implementierungsspezifischen Eigenschaften der Ganzzahltypen angeben.
<locale.h> Definiert Lokalisierungsfunktionen .
<math.h> Definiert gängige mathematische Funktionen .
<setjmp.h> Deklariert die Makros setjmpund longjmp, die für nicht lokale Exits verwendet werden.
<signal.h> Definiert Signalverarbeitungsfunktionen .
<stdalign.h> C11 Zum Abfragen und Festlegen der Ausrichtung von Objekten.
<stdarg.h> Für den Zugriff auf eine unterschiedliche Anzahl von Argumenten, die an Funktionen übergeben werden.
<stdatomic.h> C11 Für atomare Operationen an Daten, die von Threads gemeinsam genutzt werden.
<stdbool.h> C99 Definiert einen booleschen Datentyp .
<stddef.h> Definiert mehrere nützliche Typen und Makros .
<stdint.h> C99 Definiert Integertypen mit exakter Breite .
<stdio.h> Definiert zentrale Eingabe- und Ausgabefunktionen
<stdlib.h> Definiert numerische Konvertierungsfunktionen , Pseudozufallszahlen - Erzeugungsfunktionen , Speicherzuweisung , Prozeßsteuerfunktionen
<stdnoreturn.h> C11 Zur Angabe von Sperrfunktionen
<string.h> Definiert String-Handling-Funktionen
<tgmath.h> C99 Definiert typgenerische mathematische Funktionen .
<threads.h> C11 Definiert Funktionen zum Verwalten mehrerer Threads , Mutexe und Bedingungsvariablen
<time.h> Definiert Datums- und Zeithandhabungsfunktionen
<uchar.h> C11 Typen und Funktionen zur Manipulation von Unicode- Zeichen
<wchar.h> NA1 Definiert Wide-String-Handling-Funktionen
<wctype.h> NA1 Definiert eine Reihe von Funktionen, die verwendet werden, um breite Zeichen nach ihrem Typ zu klassifizieren oder zwischen Groß- und Kleinschreibung zu konvertieren

Drei der Headerdateien ( complex.h, stdatomic.h, und threads.h) sind bedingte Funktionen, die von Implementierungen nicht unterstützt werden müssen.

Der POSIX- Standard fügte mehrere nicht standardmäßige C-Header für Unix-spezifische Funktionalität hinzu. Viele haben den Weg zu anderen Architekturen gefunden. Beispiele sind fcntl.hund unistd.h. Eine Reihe anderer Gruppen verwenden andere nicht standardmäßige Header – die GNU C Library hat alloca.h, und HP OpenVMS hat die va_count()Funktion.

Dokumentation

Auf Unix-ähnlichen Systemen wird die maßgebliche Dokumentation der tatsächlich implementierten API in Form von Manpages bereitgestellt . Auf den meisten Systemen befinden sich Manpages zu Standardbibliotheksfunktionen in Abschnitt 3; Abschnitt 7 kann einige allgemeinere Seiten zu den zugrunde liegenden Konzepten enthalten (zB man 7 math_errorin Linux ).

Implementierungen

Unix-ähnliche Systeme haben normalerweise eine C-Bibliothek in Form einer gemeinsam genutzten Bibliothek , aber die Header-Dateien (und die Compiler-Toolchain) können in einer Installation fehlen, sodass eine C-Entwicklung möglicherweise nicht möglich ist. Die C-Bibliothek wird auf Unix-ähnlichen Systemen als Teil des Betriebssystems betrachtet. Die C-Funktionen, einschließlich der ISO-C-Standardfunktionen, werden von Programmen häufig verwendet und gelten nicht nur als Implementierung von etwas in der Sprache C, sondern de facto auch als Teil der Betriebssystemschnittstelle. Unix-ähnliche Betriebssysteme können im Allgemeinen nicht funktionieren, wenn die C-Bibliothek gelöscht wird. Dies gilt für Anwendungen, die dynamisch im Gegensatz zu statisch verknüpft sind. Außerdem arbeitet der Kernel selbst (zumindest im Fall von Linux) unabhängig von irgendwelchen Bibliotheken.

Unter Microsoft Windows stellen die dynamischen Kernbibliotheken ( DLLs ) eine Implementierung der C-Standardbibliothek für den Microsoft Visual C++- Compiler v6.0 bereit; die C-Standardbibliothek für neuere Versionen des Microsoft Visual C++-Compilers wird von jedem Compiler einzeln bereitgestellt, ebenso wie verteilbare Pakete. In C geschriebene kompilierte Anwendungen werden entweder statisch mit einer C-Bibliothek verknüpft oder mit einer dynamischen Version der Bibliothek verknüpft, die mit diesen Anwendungen geliefert wird, anstatt sich darauf zu verlassen, dass sie auf den Zielsystemen vorhanden ist. Funktionen in der C-Bibliothek eines Compilers gelten nicht als Schnittstellen zu Microsoft Windows.

Es gibt viele andere Implementierungen, die sowohl mit verschiedenen Betriebssystemen als auch mit C-Compilern bereitgestellt werden. Einige der beliebtesten Implementierungen sind die folgenden:

  • Die BSD libc , verschiedene Implementierungen, die mit von BSD abgeleiteten Betriebssystemen vertrieben werden
  • GNU-C-Bibliothek (glibc), verwendet in GNU Hurd , GNU/kFreeBSD und Linux
  • Microsoft C-Laufzeitbibliothek , Teil von Microsoft Visual C++
  • dietlibc , eine alternative kleine Implementierung der C-Standardbibliothek (MMU-less)
  • μClibc , eine C-Standardbibliothek für eingebettete μClinux- Systeme (MMU-less)
  • Newlib , eine C-Standardbibliothek für eingebettete Systeme (MMU-less) und wird in der Cygwin GNU-Distribution für Windows verwendet
  • klibc , hauptsächlich zum Booten von Linux-Systemen
  • musl , eine weitere leichtgewichtige C-Standardbibliotheksimplementierung für Linux-Systeme
  • Bionic , ursprünglich von Google für das Android Embedded System Betriebssystem entwickelt, abgeleitet von BSD libc

Compiler-integrierte Funktionen

Einige Compiler (z. B. GCC ) bieten integrierte Versionen vieler Funktionen der C-Standardbibliothek; das heißt, die Implementierungen der Funktionen werden in die kompilierte Objektdatei geschrieben , und das Programm ruft die integrierten Versionen anstelle der Funktionen in der gemeinsam genutzten Objektdatei der C-Bibliothek auf . Dies reduziert den Overhead von Funktionsaufrufen, insbesondere wenn Funktionsaufrufe durch Inline- Varianten ersetzt werden, und ermöglicht andere Formen der Optimierung (da der Compiler die Kontrollflusseigenschaften der eingebauten Varianten kennt ), kann aber beim Debuggen zu Verwirrung führen (z , die Einbauversionen können nicht durch instrumentierte Varianten ersetzt werden).

Die eingebauten Funktionen müssen sich jedoch wie normale Funktionen gemäß ISO C verhalten. Die Hauptimplikation ist, dass das Programm in der Lage sein muss, einen Zeiger auf diese Funktionen zu erstellen, indem es ihre Adresse nimmt und die Funktion mit diesem Zeiger aufruft. Wenn zwei Zeiger auf dieselbe Funktion in zwei verschiedenen Übersetzungseinheiten im Programm abgeleitet werden, müssen diese beiden Zeiger gleich sein; das heißt, die Adresse kommt durch Auflösen des Namens der Funktion, die eine externe (programmweite) Verknüpfung hat.

Verlinkung, libm

Unter FreeBSD und glibc sind einige Funktionen wie sin() standardmäßig nicht eingebunden, sondern in der mathematischen Bibliothek libm enthalten . Wenn einer von ihnen verwendet wird, muss dem Linker die Direktive gegeben werden -lm. POSIX erfordert, dass der c99-Compiler unterstützt -lmund dass die in den Headern deklarierten Funktionen math.h, complex.h, und fenv.hzum Linken verfügbar sind, wenn -lmangegeben wird, gibt jedoch nicht an, ob die Funktionen standardmäßig gelinkt sind. musl erfüllt diese Anforderung, indem es alles in eine einzige libc-Bibliothek packt und eine leere libm bereitstellt.

Erkennung

Gemäß dem C-Standard muss das Makro __STDC_HOSTED__auf 1 definiert werden, wenn die Implementierung gehostet wird. Eine gehostete Implementierung verfügt über alle vom C-Standard angegebenen Header. Eine Implementierung kann auch freistehend sein, was bedeutet, dass diese Header nicht vorhanden sind. Wenn eine Implementierung freistehend ist , muss sie __STDC_HOSTED__auf 0 definiert werden .

Probleme und Problemumgehungen

Pufferüberlauf-Schwachstellen

Einige Funktionen in der C-Standardbibliothek sind seit ihrer Einführung dafür berüchtigt, Pufferüberlauf- Schwachstellen aufzuweisen und allgemein fehlerhafte Programmierung zu fördern. Die am häufigsten kritisierten Artikel sind:

  • String-Manipulationsroutinen , einschließlich strcpy()und strcat(), wegen fehlender Überprüfung der Grenzen und möglicher Pufferüberläufe, wenn die Grenzen nicht manuell überprüft werden;
  • String-Routinen im Allgemeinen, für Nebeneffekte , die unverantwortliche Puffernutzung fördern, nicht immer eine gültige nullterminierte Ausgabe garantieren , lineare Längenberechnung;
  • printf()Familie von Routinen, um den Ausführungsstapel zu verderben , wenn die Formatzeichenfolge nicht mit den angegebenen Argumenten übereinstimmt. Dieser grundlegende Fehler führte zu einer ganzen Klasse von Angriffen: Format-String-Angriffe ;
  • gets()und scanf()Familie von E/A-Routinen, mangels (entweder einer oder einfacher) Überprüfung der Eingabelänge.

Mit Ausnahme des Extremfalls bei gets()können alle Sicherheitslücken vermieden werden, indem Hilfscode zur Durchführung von Speicherverwaltung, Grenzüberprüfung, Eingabeüberprüfung usw. eingeführt wird. Dies geschieht häufig in Form von Wrappern, die Standardbibliotheksfunktionen sicherer und benutzerfreundlicher machen. Dies geht bereits auf das Buch The Practice of Programming von B. Kernighan und R. Pike zurück, in dem die Autoren häufig Wrapper verwenden, die Fehlermeldungen ausgeben und das Programm beenden, wenn ein Fehler auftritt.

Das ISO C-Komitee hat die technischen Berichte TR 24731-1 veröffentlicht und arbeitet an TR 24731-2, um die Übernahme einiger Funktionen mit Bounds Checking und automatischer Pufferzuweisung entsprechend vorzuschlagen. Ersteres stößt auf heftige Kritik und einiges Lob, letzteres auf gemischte Reaktionen. Trotzdem wurde TR 24731-1 in die C-Standardbibliothek von Microsoft implementiert und der Compiler gibt Warnungen aus, wenn alte "unsichere" Funktionen verwendet werden.

Threading-Probleme, Anfälligkeit für Race-Bedingungen

Die strerror()Routine wird kritisiert, weil sie Thread-unsicher und ansonsten anfällig für Race-Bedingungen ist .

Fehlerbehandlung

Die Fehlerbehandlung der Funktionen in der C-Standardbibliothek ist nicht konsistent und manchmal verwirrend. Laut der Linux-Handbuchseite math_error"Die aktuelle (Version 2.8) Situation unter glibc ist chaotisch. Die meisten (aber nicht alle) Funktionen lösen bei Fehlern Ausnahmen aus. Einige setzen auch errno . Einige Funktionen setzen errno , lösen aber keine Ausnahme aus . Einige wenige Funktionen tun beides nicht."

Standardisierung

Die ursprüngliche Sprache C bot im Gegensatz zu traditionellen Sprachen wie COBOL und Fortran keine integrierten Funktionen wie E/A-Operationen . Im Laufe der Zeit teilten Benutzergemeinschaften von C Ideen und Implementierungen dessen, was heute als C-Standardbibliotheken bezeichnet wird. Viele dieser Ideen flossen schließlich in die Definition der standardisierten Sprache C ein.

Sowohl Unix als auch C wurden in den späten 1960er und frühen 1970er Jahren in den Bell Laboratories von AT&T entwickelt . In den 1970er Jahren wurde die Sprache C immer beliebter. Viele Universitäten und Organisationen begannen, für ihre eigenen Projekte eigene Varianten der Sprache zu entwickeln. Zu Beginn der 1980er Jahre wurden Kompatibilitätsprobleme zwischen den verschiedenen C-Implementierungen offensichtlich. 1983 bildete das American National Standards Institute (ANSI) ein Komitee, um eine Standardspezifikation von C, bekannt als „ ANSI C “, zu erstellen . Diese Arbeit gipfelte in der Schaffung des sogenannten C89-Standards im Jahr 1989. Ein Teil des resultierenden Standards war eine Reihe von Softwarebibliotheken , die als ANSI-C-Standardbibliothek bezeichnet wurden.

POSIX-Standardbibliothek

POSIX sowie SUS spezifizieren eine Reihe von Routinen, die zusätzlich zu denen in der grundlegenden C-Standardbibliothek verfügbar sein sollten. Die POSIX-Spezifikation enthält Header-Dateien für unter anderem Multithreading , Netzwerk und reguläre Ausdrücke . Diese werden oft zusammen mit der C-Standardbibliotheksfunktionalität implementiert, mit unterschiedlicher Nähe. Zum Beispiel implementiert glibc Funktionen wie forkinnerhalb libc.so, aber bevor NPTL in glibc zusammengeführt wurde, bildete es eine separate Bibliothek mit einem eigenen Linker-Flag-Argument. Oft wird diese von POSIX spezifizierte Funktionalität als Teil der Bibliothek betrachtet; die grundlegende C-Bibliothek kann als ANSI- oder ISO- C-Bibliothek identifiziert werden .

BSD-libc

BSD libc ist eine Obermenge der POSIX-Standardbibliothek, die von den C-Bibliotheken unterstützt wird, die in BSD- Betriebssystemen wie FreeBSD , NetBSD , OpenBSD und macOS enthalten sind . BSD libc hat einige Erweiterungen, die im Originalstandard nicht definiert sind, von denen viele erstmals in der 4.4BSD- Version von 1994 erschienen sind (die erste, die weitgehend nach der Veröffentlichung des ersten Standards im Jahr 1989 entwickelt wurde). Einige der Erweiterungen von BSD libc sind:

  • sys/tree.h – enthält eine Implementierung von Rot-Schwarz-Baum und Spreizbaum
  • sys/queue.h – Implementierungen von Linked List , Queues , Tail Queue , etc.
  • fgetln() – definiert in stdio.h. Damit kann eine Datei zeilenweise gelesen werden.
  • fts.h – enthält einige Funktionen zum Durchlaufen einer Dateihierarchie
  • db.h – einige Funktionen zur Verbindung mit der Berkeley DB
  • strlcat()und strlcpy() – sichere Alternativen für strncat()undstrncpy()
  • err.h – enthält einige Funktionen zum Drucken formatierter Fehlermeldungen
  • vis.h – enthält die vis()Funktion. Diese Funktion wird verwendet, um nicht druckbare Zeichen in einem visuellen Format anzuzeigen.

Die C-Standardbibliothek in anderen Sprachen

Einige Sprachen enthalten die Funktionalität der Standard-C-Bibliothek in ihren eigenen Bibliotheken. Die Bibliothek kann an die Struktur der Sprache angepasst werden, aber die operationelle Semantik wird ähnlich gehalten. Die Sprache C++ enthält zum Beispiel die Funktionalität der C-Standardbibliothek im Namensraum std (zB std::printf, std::atoi, std::feof), in Header-Dateien mit ähnlichen Namen wie die C-Dateien ( cstdio, cmath, cstdlib, etc.). Andere Sprachen, die ähnliche Ansätze verfolgen , sind D , Perl , Ruby und die Hauptimplementierung von Python, bekannt als CPython . In Python 2 zum Beispiel sind die eingebauten Dateiobjekte als "implementiert mit dem C- stdioPaket" definiert, sodass von den verfügbaren Operationen (Öffnen, Lesen, Schreiben usw.) erwartet wird, dass sie das gleiche Verhalten wie die entsprechenden C-Funktionen haben . Rust hat eine Kiste namens libc, die die Verwendung mehrerer C-Funktionen, Strukturen und anderer Typdefinitionen ermöglicht.

Vergleich mit Standardbibliotheken anderer Sprachen

Die C-Standardbibliothek ist klein im Vergleich zu den Standardbibliotheken einiger anderer Sprachen. Die C-Bibliothek bietet einen grundlegenden Satz mathematischer Funktionen, Zeichenfolgenmanipulation, Typkonvertierung und datei- und konsolenbasierte I/O. Es enthält keinen Standardsatz von " Containertypen " wie die C++ Standard Template Library , geschweige denn die vollständigen Toolkits für die grafische Benutzeroberfläche (GUI), Netzwerktools und eine Fülle anderer Funktionen, die Java und das .NET Framework standardmäßig bereitstellen. Der Hauptvorteil der kleinen Standardbibliothek besteht darin, dass die Bereitstellung einer funktionierenden ISO-C-Umgebung viel einfacher ist als bei anderen Sprachen und folglich die Portierung von C auf eine neue Plattform vergleichsweise einfach ist.

Siehe auch

Anmerkungen

Verweise

Weiterlesen

Externe Links