Heim > Backend-Entwicklung > C++ > Hauptteil

TIL CAnnex K existiert, aber Sie sollten es nicht verwenden

DDD
Freigeben: 2024-11-03 13:58:03
Original
352 Leute haben es durchsucht

TIL CAnnex K exists but you shouldn

Anhang K ist der technische Name. Weitere häufig verwendete Schlüsselwörter sind __STDC_LIB_EXT1__ und __STDC_WANT_LIB_EXT1__. Anhang K definiert die „sicheren“ _s-Suffixe wie sprintf_s() und scanf_s().

Sehen Sie sich auch die Felderfahrungen mit Anhang K (2015) und die technische Dokumentation „Grenzprüfung – cppreference.com“ an.

Das Ziel

Was ist der Sinn der _s()-Funktionen? Sie überprüfen ihre Argumente auf weitere Invarianten wie „ruft den Einschränkungshandler auf, wenn der Stream null ist, die Zeichenfolge null ist, der Bufsz-Wert null ist oder der Puffer außerhalb der Grenzen schreiben würde, die über die angegebene Länge hinausgehen“. Das scheint eine gute Idee zu sein, oder? Ja! Das tut es!

Der Kern davon ist, dass Sie Folgendes tun können/könnten:

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>

int main() {
  printf_s("Hello %s!\n", "Alan Turing");
  return 0;
}
Nach dem Login kopieren
Nach dem Login kopieren

Wie ist das im Vergleich zur normalen Vorgehensweise ohne __STDC_WANT_LIB_EXT1__?

Glücklicher Weg

FILE *file = fopen("hello.txt", "r");
// file is OK.
Nach dem Login kopieren
FILE *file;
errno_t err = fopen_s(&file, "hello.txt", "r");
// file is OK
Nach dem Login kopieren

Trauriger Weg

FILE *file = fopen("notexist.txt", "r");
// file is NULL, errno is set.
Nach dem Login kopieren
FILE *file;
errno_t err = fopen_s(&file, "notexist.txt", "r");
// file is NULL, err is set.
Nach dem Login kopieren

Schlechter Weg

FILE *file = fopen(NULL, NULL);
// idk.
Nach dem Login kopieren
FILE *file;
errno_t err = fopen_s(&file, NULL, NULL);
// Constraint violated. Abort with message.
Nach dem Login kopieren

Ja, Sie können den Einschränkungshandler so anpassen, dass er sich einfach in einer Datei protokolliert und fortfährt, als ob nichts passiert wäre.

set_constraint_handler_s(ignore_handler_s);
set_constraint_handler_s(abort_handler_s);
set_constraint_handler_s(my_awesome_handler);
Nach dem Login kopieren

Beachten Sie, dass das normale fopen() den gleichen Rückgabewert (möglicherweise eine andere Fehlernummer) hat, um unterschiedliche Schweregrade von Fehlern anzuzeigen? Genau das wollte fopen_s() verbessern. Zumindest ist das meine Lesart. Ich stelle es mir wie Rusts panic!() vs. ein zurückgegebenes Result vor. Es hilft wahrscheinlich auch, einige Pufferüberlaufangriffe zu stoppen, indem es size_of_dest-Argumente bereitstellt, um einen Überlauf von Zielpuffern wie strcpy_s() und gets_s() zu vermeiden.

char* gets( char* str ); // (removed in C11)
char* gets_s( char* str, rsize_t n ); // (since C11, annex K)
Nach dem Login kopieren

Liest stdin in das Zeichenarray, auf das str zeigt, bis ein Zeilenumbruchzeichen gefunden wird oder das Dateiende erreicht ist. Ein Nullzeichen wird unmittelbar nach dem letzten in das Array eingelesenen Zeichen geschrieben. Das Newline-Zeichen wird verworfen, aber nicht im Puffer gespeichert.

Die Funktion gets() führt keine Grenzprüfung durch, daher ist diese Funktion äußerst anfällig für Pufferüberlaufangriffe. Es kann nicht sicher verwendet werden (es sei denn, das Programm läuft in einer Umgebung, die einschränkt, was auf stdin angezeigt werden kann). Aus diesem Grund wurde die Funktion im dritten Korrigendum des C99-Standards als veraltet markiert und im C11-Standard vollständig entfernt. fgets() und gets_s() sind die empfohlenen Ersetzungen.

WARNUNG: Verwenden Sie niemals gets().

// BAD
char buffer[1000];
gets(buffer);
// ⚠️ Could write >1000 chars to `buffer`!
Nach dem Login kopieren
// GOOD
char buffer[1000];
gets_s(buffer, sizeof(buffer));
// This will stop at 1000 chars.
Nach dem Login kopieren

Die Funktion _s() scheint ziemlich praktisch zu sein, um häufig auftretende Pufferüberläufe zu stoppen.

Das Problem

Sie sind nicht überall implementiert. Die _s()-Funktionen sind eine Erweiterung, die in libc-Implementierungen wie GNUs glibc nicht verfügbar ist. Es gibt noch andere kleinere Probleme, wie etwa die Unergonomie für Multithreading und den häufigen Fehler, sizeof(src) anstelle von sizeof(dest) für Dinge wie strcpy_s() zu verwenden, aber das alles verblasst im Vergleich zum Verfügbarkeitsproblem.

Die meisten Online-Informationen, die ich finden kann, scheinen darauf hinzudeuten, dass MSVC der einzige große Compiler/Libc ist, der Annex K implementiert hat.

Angesichts der Tatsache, dass diese ausgefallenen _s()-Funktionen nicht überall vorhanden sind, wo Ihr Code kompiliert werden muss, müssten Sie Code wie diesen schreiben:

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>

int main() {
  printf_s("Hello %s!\n", "Alan Turing");
  return 0;
}
Nach dem Login kopieren
Nach dem Login kopieren

...für jede Instanz, die Sie strlen_s() oder fopen_s() oder strcpy_s() ausführen möchten. Das ist eine gute Möglichkeit, verrückt zu werden.

Natürlich werden Sie also keinen plattformabhängigen Code schreiben nur um grundlegende printf()- und strcpy()-Funktionen auszuführen, aber wie wäre es mit dem Einpacken all dieser #ifdef __STDC_LIB_EXT1__ #else-Sachen in eine Bibliothek?

Es gab zwei vielversprechend aussehende Bibliotheken, die ich über eine schnelle Google-Suche gefunden habe:

  • safec: GitHub-Seite der Safe C Library-Website ⭐335
  • sbaresearch/slibc: Implementierung von C11 Anhang K „Grenzprüfungsschnittstellen“ ISO/IEC 9899:2011 ⭐14

Also... wenn Sie _s()-Funktionen verwenden möchten (oder aus Sicherheitsgründen dazu verpflichtet sind), sich aber auch nicht nur auf MSVC beschränken möchten, können Sie eine dieser ☝ Bibliotheken verwenden.

? Weitere Informationen finden Sie unter Felderfahrung mit Anhang K (2015) und in der technischen Dokumentation „Grenzprüfung – cppreference.com“.

Das obige ist der detaillierte Inhalt vonTIL CAnnex K existiert, aber Sie sollten es nicht verwenden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage