Direkte Antwort auf die Frage
Ich mag Roberts Antwort, aber ich habe auch einige Ansichten zu den Fragen, die ich aufgeworfen habe.
Verwenden Sie eine Bibliothek oder einen Compiler mit Unterstützung für die Funktionen TR24731-1?
Nein, ich nicht.
Wenn ja, welcher Compiler oder welche Bibliothek und auf welcher Plattform?
Ich glaube, die Funktionen werden von MS Visual Studio bereitgestellt (z. B. MS VC ++ 2008 Edition), und es gibt Warnungen, die Sie dazu ermutigen, sie zu verwenden.
Haben Sie Fehler beim Korrigieren Ihres Codes zur Verwendung dieser Funktionen entdeckt?
Noch nicht. Und ich erwarte nicht, viele in meinem Code aufzudecken. Einige der anderen Codes, mit denen ich arbeite - vielleicht. Aber ich muss noch überzeugt werden.
Welche Funktionen bieten den größten Wert?
Ich mag die Tatsache, dass die Funktionsfamilie printf_s () den Formatbezeichner ' %n
' nicht akzeptiert .
Gibt es welche, die keinen Wert oder negativen Wert liefern?
Das tmpfile_s()
undtmpnam_s()
Funktionen sind eine schreckliche Enttäuschung. Sie mussten wirklich so arbeiten, mkstemp()
dass beide die Datei erstellen und öffnen, um sicherzustellen, dass keine TOCTOU-Sicherheitslücke (Time-of-Check, Time-of-Use) besteht. Derzeit bieten diese beiden nur einen sehr geringen Wert.
Ich denke auch, dass strerrorlen_s()
das sehr wenig Wert bietet.
Planen Sie, die Bibliothek in Zukunft zu nutzen?
Ich habe zwei Gedanken darüber. Ich begann mit der Arbeit an einer Bibliothek, die die Funktionen von TR 24731 gegenüber einer Standard-C-Bibliothek implementieren würde, wurde jedoch von der Menge an Unit-Tests überrascht, die erforderlich waren, um zu demonstrieren, dass sie ordnungsgemäß funktioniert. Ich bin mir nicht sicher, ob ich das fortsetzen soll. Ich habe Code, den ich auf Windows portieren möchte (hauptsächlich aus dem perversen Wunsch heraus, Unterstützung auf allen Plattformen bereitzustellen - er arbeitet seit einigen Jahrzehnten an Unix-Derivaten). Um es ohne Warnungen der MSVC-Compiler kompilieren zu können, muss ich den Code leider mit Dingen versehen, um zu verhindern, dass MSVC mit den absolut zuverlässigen (bei sorgfältiger Verwendung) Standardfunktionen der C-Bibliothek über mich witzelt. Und das ist nicht appetitlich. Es ist schon schlimm genug, dass ich mich mit den meisten zwei Jahrzehnten eines Systems auseinandersetzen muss, das sich in dieser Zeit entwickelt hat. Es ist ärgerlich, sich mit der Vorstellung von Spaß beschäftigen zu müssen (Menschen dazu zu bringen, TR 24731 zu übernehmen, wenn sie es nicht brauchen). Dies war teilweise der Grund, warum ich mit der Bibliotheksentwicklung begonnen habe, damit ich unter Unix und Windows dieselben Schnittstellen verwenden kann. Aber ich bin mir nicht sicher, was ich von hier aus machen werde.
Verfolgen Sie die Arbeit des TR24731-2 überhaupt?
Ich habe es nicht verfolgt, bis ich zur Standardseite gegangen bin, während ich die Daten für die Frage gesammelt habe. Die asprintf()
und vasprintf()
Funktionen sind wahrscheinlich wertvoll; Ich würde die benutzen. Ich bin mir nicht sicher über die Speicherstrom-E / A-Funktionen. Eine strdup()
Standardisierung auf C-Ebene wäre ein großer Fortschritt. Dies scheint mir weniger kontrovers zu sein als die Schnittstellen von Teil 1 (Bounds Checking).
Insgesamt bin ich von Teil 1 'Bounds-Checking Interfaces' nicht überzeugt. Das Material im Entwurf von Teil 2 'Dynamische Zuordnungsfunktionen' ist besser.
Wenn es nach mir ginge, würde ich mich etwas in Richtung von Teil 1 bewegen, aber ich hätte auch die Schnittstellen in der C99-Standard-C-Bibliothek überarbeitet, die a char *
an den Anfang der Zeichenfolge zurückgeben (z. B. strcpy()
und strcat()
), so dass anstelle von Wenn sie einen Zeiger auf den Start zurückgeben, geben sie einen Zeiger auf das Nullbyte am Ende der neuen Zeichenfolge zurück. Dies würde einige gängige Redewendungen (wie das wiederholte Verketten von Zeichenfolgen am Ende eines anderen) effizienter machen, da es trivial wäre, das quadratische Verhalten von Code zu vermeiden, der wiederholt verwendet wird strcat()
. Die Ersetzungen würden alle eine Nullterminierung von Ausgabezeichenfolgen sicherstellen, wie dies bei den TR24731-Versionen der Fall ist. Ich bin weder der Idee der Überprüfungsschnittstelle noch den Ausnahmebehandlungsfunktionen völlig abgeneigt. Es ist eine knifflige Angelegenheit.
Die Implementierung von Microsoft entspricht nicht der Standardspezifikation
Update (08.05.2011)
Siehe auch diese Frage . Leider und fatal für die Nützlichkeit der TR24731-Funktionen unterscheiden sich die Definitionen einiger Funktionen zwischen der Microsoft-Implementierung und dem Standard, was sie (für mich) unbrauchbar macht. Meine Antwort dort zitiert vsnprintf_s()
.
Zum Beispiel sagt TR 24731-1, dass die Schnittstelle zu vsnprintf_s()
:
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdarg.h>
#include <stdio.h>
int vsnprintf_s(char * restrict s, rsize_t n,
const char * restrict format, va_list arg);
Leider sagt MSDN, dass die Schnittstelle zu vsnprintf_s()
:
int vsnprintf_s(
char *buffer,
size_t sizeOfBuffer,
size_t count,
const char *format,
va_list argptr
);
Parameter
- buffer - Speicherort für die Ausgabe.
- sizeOfBuffer - Die Größe des Puffers für die Ausgabe.
- count - Maximale Anzahl der zu schreibenden Zeichen (ohne die abschließende Null) oder _TRUNCATE.
- format - Formatspezifikation.
- argptr - Zeiger auf die Liste der Argumente.
Beachten Sie, dass dies nicht nur eine Frage der Typzuordnung ist: Die Anzahl der festen Argumente ist unterschiedlich und daher nicht miteinander vereinbar. Mir (und vermutlich auch dem Normungsausschuss) ist auch unklar, welchen Nutzen es hat, sowohl "sizeOfBuffer" als auch "count" zu haben. Es sieht aus wie die gleichen Informationen zweimal (oder zumindest wird Code normalerweise mit dem gleichen Wert für beide Parameter geschrieben).
Ebenso gibt es auch Probleme mit scanf_s()
und seinen Verwandten. Microsoft gibt an, dass der Typ des Pufferlängenparameters unsigned
(explizit "Der Größenparameter ist vom Typ unsigned
, nicht size_t
") ist. Im Gegensatz dazu ist in Anhang K der Größenparameter vom Typ rsize_t
, der die eingeschränkte Variante von ist size_t
( rsize_t
ist ein anderer Name für size_t
, ist aber RSIZE_MAX
kleiner als SIZE_MAX
). Daher scanf_s()
müsste der Codeaufruf für Microsoft C und Standard C unterschiedlich geschrieben werden.
Ursprünglich hatte ich vor, die "sicheren" Funktionen zu verwenden, um Code unter Windows und Unix sauber zu kompilieren, ohne bedingten Code schreiben zu müssen. Da dies nicht funktioniert, weil die Microsoft- und ISO-Funktionen nicht immer gleich sind, ist es ziemlich an der Zeit, aufzugeben.
Änderungen an Microsoft vsnprintf()
in Visual Studio 2015
In der Visual Studio 2015-Dokumentation für vsnprintf()
wird darauf hingewiesen, dass sich die Benutzeroberfläche geändert hat:
Beginnend mit dem UCRT in Visual Studio 2015 und Windows 10 vsnprintf
ist nicht mehr identisch mit _vsnprintf
. Die vsnprintf
Funktion entspricht dem C99-Standard; _vnsprintf
wird aus Gründen der Abwärtskompatibilität beibehalten.
Die Microsoft-Oberfläche für vsnprintf_s()
hat sich jedoch nicht geändert.
Weitere Beispiele für Unterschiede zwischen Microsoft und Anhang K.
Die C11-Standardvariante von localtime_s()
ist in ISO / IEC 9899: 2011 Anhang K.3.8.2.4 definiert als:
struct tm *localtime_s(const time_t * restrict timer,
struct tm * restrict result);
verglichen mit der MSDN-Variante localtime_s()
definiert als:
errno_t localtime_s(struct tm* _tm, const time_t *time);
und die POSIX-Variante localtime_r()
definiert als:
struct tm *localtime_r(const time_t *restrict timer,
struct tm *restrict result);
Die C11-Standard- und POSIX-Funktionen sind bis auf den Namen gleichwertig. Die Microsoft-Funktion unterscheidet sich in der Benutzeroberfläche, obwohl sie einen Namen mit dem C11-Standard teilt.
Ein weiteres Beispiel für Unterschiede ist Microsoft ‚s strtok_s()
und Anhang K die strtok_s()
:
char *strtok_s(char *strToken, const char *strDelimit, char **context);
vs:
char *strtok_s(char * restrict s1, rsize_t * restrict s1max, const char * restrict s2, char ** restrict ptr);
Beachten Sie, dass die Microsoft-Variante 3 Argumente hat, während die Annex K-Variante 4 hat. Dies bedeutet, dass die Argumentliste zu Microsoft strtok_s()
mit POSIX kompatibel iststrtok_r()
Aufrufe an diese sind also effektiv austauschbar, wenn Sie den Funktionsnamen ändern (z. B. durch ein Makro) Die Version Standard C (Anhang K) unterscheidet sich von beiden mit dem zusätzlichen Argument.
Die Frage Unterschiedliche Deklarationen von qsort_r()
Mac und Linux hat eine Antwort, die auch qsort_s()
wie von Microsoft und qsort_s()
TR24731-1 definiert diskutiert wird - auch hier sind die Schnittstellen unterschiedlich.
ISO / IEC 9899: 2011 - C11-Norm
Der C11-Standard ( Entwurf vom Dezember 2010 ; Sie können auf einmal eine PDF-Kopie des endgültigen Standards ISO / IEC 9899: 2011 vom ANSI-Webshop für 30 USD erhalten) enthält optional die TR24731-1-Funktionen Teil des Standards. Sie sind in Anhang K (Bounds-Checking Interfaces) definiert, der eher "normativ" als "informativ" ist, aber optional.
Der C11-Standard enthält keine TR24731-2-Funktionen - was traurig ist, da die vasprintf()
Funktion und ihre Verwandten wirklich nützlich sein könnten.
Kurze Zusammenfassung:
- C11 enthält TR24731-1
- C11 enthält kein TR24731-2
- C18 ist dasselbe wie C11 für TR24731.
Vorschlag, Anhang K aus dem Nachfolger von C11 zu streichen
Deduplicator wies in einem Kommentar zu einer anderen Frage darauf hin, dass dem ISO C-Standardausschuss (ISO / IEC JTC1 / SC22 / WG14) ein Vorschlag vorliegt.
Es enthält Verweise auf einige der vorhandenen Implementierungen der Funktionen in Anhang K - keine davon ist weit verbreitet (Sie können sie jedoch bei Interesse über das Dokument finden).
Das Dokument endet mit der Empfehlung:
Daher schlagen wir vor, Anhang K entweder aus der nächsten Überarbeitung des C-Standards zu entfernen oder veraltet und dann zu entfernen.
Ich unterstütze diese Empfehlung.
Die C18-Norm hat den Status von Anhang K nicht geändert . Es gibt ein Papier N2336, in dem befürwortet wird, einige Änderungen an Anhang K vorzunehmen, um seine Mängel zu beheben , anstatt ihn vollständig zu beseitigen.
strlen()
Zum Code hinzufügen" meinen . Es gibt definitiv Zeiten, in denenstrlen()
die Antwort nicht richtig ist, z. B. wenn ein Puffer an eine E / A-Funktion übergeben wird (z. B.gets_s()
). Aber vielleicht können Sie näher darauf eingehen, woran Sie denken?