2014-04-26 4 views
9

Wie wir alle wissen, ist strcpy_s eine Sicherheitsversion von strcpy.Wie funktioniert strcpy_s?

Aber ich frage mich, wie es funktioniert ...

lassen Sie uns einige Beispiele sehen.

strpy_s Erklärung:
errno_t strcpy_s (_CHAR * _DEST, size_t _SIZE, Konst _CHAR * _SRC)

EG1

char dest[5]; 
char* src = "abcdefg"; 
strcpy_s(dest,5,src); 

Es wird eine Behauptung zurück.
Ich glaube, ich das verstehen kann, verwenden Sie _SIZE sicherzustellen, dass wir nicht mehr Zeichen als _SIZE

kopieren Aber .. ich das nicht verstehen kann:

char dest[5]; 
char* src = "abcdefg"; 
strcpy_s(dest,10,src); 

wir können bekomme immer noch eine Behauptung, wie ist das passiert?

ps, ​​Fehler war:

Debug Assertionsfehler
Ausdruck: wird strcpy_s (L & & 0 "Puffer zu klein ist")


In VS2013

prüft die Größe von dest in seinem Körper? und wenn es stimmt, wie? Wie überprüfe ich einen Zeiger wie _DEST?

+0

Lesen Sie die Dokumentation sorgfältig: [MSDN] (http://msdn.microsoft.com/en-us/library/td1esda9.aspx) – Jens

+0

Ihr zweites Beispiel ist falsch. Der Parameter _SIZE muss die Größe des Puffers korrekt angeben. Wenn Sie 10 für _SIZE geben, aber Ihr Puffer nur 5 ist, ist das Ergebnis nicht definiert. Es gibt keine Möglichkeit, dass strcpy_s diesen Fehler finden kann. – Brandin

+0

tatsächlich gab es eine Behauptung. – Joey

Antwort

8

Dies ist, wie eigentlich die Größe eines Stapels Array zur Laufzeit zu erhalten, ohne es in einen Zeiger abklingenden:

template<typename T, size_t N> 
size_t arrSize(T (&array)[N]) 
{ 
    return N; 
} 

Sie es als Vorlage Referenz senden, und die Template-Mechanismus leitet daraus die Größe. Also, Sie so etwas wie

int myArray[10]; 
cout << arrSize(myArray); // will display 10 

tun können, so meine Vermutung ist, dass dies ist, wie der „sichere“ MS strcpy_s ist die Größe zu überprüfen. Andernfalls, wenn Sie nur einen Zeiger übergeben, gibt es keine Standard-COMPLIANT Weise die Größe bekommen

+0

guter Punkt! Ich bin nicht so vertraut mit C++, denke, ich brauche etwas Zeit auf Vorlage in C++ :) danke! – Joey

1

dest kann nicht mehr als 5 Zeichen enthalten, deshalb erhalten Sie den Fehler. Es ist nicht wegen _SIZE. Wenn destchar* war, dann müssen Sie sicherstellen, dass Sie genügend Speicher dafür reservieren, Sie werden keinen Kompilierungsfehler bekommen. Aber in Ihrem Programm dest hat eine feste Größe, und strcpy_s, im Gegensatz zu strcpy, überprüft die Größe des Zielpuffers (wenn es kann, und in diesem Fall kann es wie seine Größe zum Zeitpunkt der Kompilierung definiert ist). Lesen Sie diese

http://www.cplusplus.com/forum/beginner/118771/

Grundsätzlich strcpy_s ist die "sichere" Version von strcpy, es nicht zulassen, dass Sie überfluten zu. Aus dem Standard: C (2011) und ISO/IEC WDTR 24731 - strcpy_s: eine Variante von strcpy, die die Zielpuffergröße vor dem Kopieren überprüft. Intern, vermutlich strcpy_s behauptet sizeof(dest)<SIZE.

+0

Wie überprüft man die Zielpuffergröße? – Joey

+0

mit 'sizeof', ich habe gerade meinen Kommentar bearbeitet :) Aber es funktioniert nur für statisch definierte Arrays, nicht für Zeiger, für die der Compiler nicht weiß, wieviel Speicher (falls vorhanden) Sie zugewiesen haben. – vsoftco

+0

so können wir nicht die Größe des dest bekommen? – Joey

1

MSDN sagt „Die strcpy_s Funktion kopiert den Inhalt in der Adresse des strSource, einschließlich dem abschließenden Nullzeichens, an den Ort, der von strDestination angegeben wird. Die Zielstring groß genug sein muss, die Quellzeichenfolge und seinen Abschluss zu halten Nullzeichen Das Verhalten von strcpy_s ist nicht definiert, wenn die Quell- und Zielzeichenfolgen sich überlappen."

+0

also war es nicht so "sicher"? – Joey

+0

Was ist Ihre Definition von sicher? –

+0

wenn wir versuchen, diese Funktion wie strcpy_s (dest, 10, src) zu verwenden; wir erhalten eine Ausnahme oder werden nichts tun – Joey

1

Im DEBUG-Modus füllen MicroSoft-APIs den Puffer mit 0xfd, damit sie auf einen Überlauf prüfen können.

Diese Funktion schneidet die kopierte Zeichenfolge nicht ab, sondern löst eine Ausnahme aus!

Es ist immer ein Problem die Größe des Zielpuffers anzugeben (benutze _countof statt sizeof), meistens wenn du einen Zeiger benutzt!

Ich habe mehr Probleme mit diesen "_s" APIs als mit den Normen !!