2016-05-12 7 views
-1

ich so verwirrt bin, tut mir leid, wenn dies offensichtlich, aber:String Kopie sagt Puffer zu klein ist, strcpy_s Quelle Ausgabe

int main() 
{ 
    char stringDest[20]; 
    char stringSource[20]; 

    strcpy_s(stringDest, stringSource); 

    return 0; 
} 

die Ausnahme auslöst „Buffer ist zu klein“. Während:

char stringSource[20]; 

int main() 
{ 
    char stringDest[20]; 

    strcpy_s(stringDest, stringSource); 

    return 0; 
} 

Funktioniert gut.

Außerdem dachte ich, der Punkt des sicheren strcpy_s(dest, size, source) war, dass man die Anzahl der Bytes an, die kopiert werden, aber wenn ich dies tun:

int main() 
{ 
    char stringDest[20]; 
    char stringSource[20]; 

    strcpy_s(stringDest, 1, stringSource); 

    return 0; 
} 

ich ein „Puffer zu klein Ausnahme ist“. Ich bin so verwirrt. Warum macht die Deklaration der Variablen außerhalb von main() einen Unterschied? Und warum ist es falsch, 1 Byte zum Kopieren anzugeben?

+1

Es ist undefiniertes Verhalten, nicht initialisierte Variablen zu lesen. –

+1

Ich weiß, dass Sie eine Antwort darauf wollen, aber anstatt sich damit zu beschäftigen, können Sie einfach 'std :: string's verwenden und' std :: string foo = "foo"; Std :: Stringleiste; bar = foo; 'und jetzt' bar' hat '" foo "' drin. – NathanOliver

+1

'errno_t strcpy_s ( char * strDestination, size_t numberOfElements, const char * strSource );' – BLUEPIXY

Antwort

5

Gibt mir eine nicht behandelte RangeChecks Ausnahme, während:

C des Arrays sind Null indiziert, das heißt für char stringSource[20]; sind die Elemente von 0 bis 19, wenn Sie stringSource[20] = '\0'; tun, ist der Zugriff aus Array-Grenzen, die zu undefiniertem Verhalten führen.

Wirft die Ausnahme "Puffer ist zu klein". Während:

Das ist, weil stringSource von dynamischem Speicher und ist nicht auf eine gültige Zeichenfolge initialisiert, Gebrauch davon nicht definiertes Verhalten verursachen.

Während der zweite Fall, wenn Sie char stringSource[20]; aus der Funktion gesetzt, das Array statischer Speicher ist, ist es Standard, indem sie mit Nullwert initialisiert, ist es das Gleiche wie char stringSource[20] = "";, das ist, warum dieser Fall der strcpy gelungen.

+0

Oh, natürlich fühle ich mich so dumm !!! – Zebrafish

+0

@TitoneMaurice Habe gerade meinen Beitrag mit dem anderen Problem aktualisiert. – fluter

2

Sie rufen hier ein undefiniertes Verhalten auf, weil Sie die Quellzeichenfolge nicht initialisieren.

In den meisten Fällen wird es Müll sein, und das erste 0 Byte ist höchstwahrscheinlich nach der Länge von 20, weshalb der Compiler/Laufzeit sich beschweren.

char stringSource[20] = {0}; 

oder alternativ

char stringSource[20] = ""; 

Was auch immer am besten passt.

Je nach Umgebung kann der Compiler in der Debug-Version absichtlich die Variablen mit Werten wie 0xff füllen, so dass der erste 0-byte immer über dem Grenzwert liegt.

Wenn Sie char stringDest[20] außerhalb der Funktion setzen, wird es eine globale Variable sein, die durch den CRT-Start immer auf 0 initialisiert wird. In Ihrem letzten Beispiel sollten Sie sich die Beschreibung strcpy_s ansehen.

Diese Variante wird einen Fehler verursachen, wenn

destsz weniger oder gleich strnlen_s ist (src, destsz); mit anderen Worten würde, Abschneiden auftreten

strcpy_s(stringDest, 1, stringSource); bedeutet, dass 1 kleiner als Ihre uninitialized StringLen, so gibt es einen Fehler.

Beachten Sie, dass dieser Parameter die Funktion nicht angibt, wie viele Zeichen er kopieren soll, aber wie groß das Ziel sein soll. Sie sagen ihm nicht, dass er nur 1 Zeichen kopieren soll, Sie sagen ihm, dass er höchstens 1 Zeichen kopieren kann (was sowieso für das 0 Byte benötigt würde).

+0

Warum muss die Zeichenfolge * destination * initialisiert werden? –

+0

In diesem Beispiel ist es nicht unbedingt notwendig, aber es ist in der Regel ratsam, Variablen zu initialisieren. – Devolus

+0

@BLUEPIXY, Sie haben Recht, ich habe das behoben. – Devolus

Verwandte Themen