Verhalten von malloc (0)

8
%Vor%

Wenn der obige Code kompiliert und ausgeführt wird, kann das Programm die Zeichenfolge lesen, obwohl wir dem Zeiger p einen 0-Byte-Speicher zugewiesen haben.

Was passiert eigentlich in der Anweisung p = (char* ) malloc(0) ?

    
svKris 21.05.2012, 11:42
quelle

3 Antworten

12

Es ist die Implementierung definiert, die malloc() zurückgibt, aber es ist ein undefiniertes Verhalten, diesen Zeiger zu verwenden. Und undefiniertes Verhalten bedeutet, dass alles wörtlich passieren kann, vom Programm arbeiten ohne Fehler bis zum Absturz, alle sicheren Wetten sind aus.

C99 Standard:

7.22.3 Speicherverwaltungsfunktionen
Absatz 1:

  

Wenn die Größe des angeforderten Speicherplatzes Null ist, ist das Verhalten implementierungsdefiniert: Entweder wird ein Nullzeiger zurückgegeben oder das Verhalten ist so, als wäre die Größe ein Wert ungleich Null, außer dass der zurückgegebene Zeiger nicht verwendet werden soll Zugriff auf ein Objekt.

    
Alok Save 21.05.2012, 11:43
quelle
0

Zusätzlich zu Als Kommentar - was passiert: Sie schreiben irgendwo in den Speicher und holen die Daten von dort ab. Je nach System und Betriebssystemtyp erhalten Sie also eine Ausnahme oder nur ein undefiniertes Verhalten

    
michelmm 21.05.2012 12:29
quelle
0

Aus reiner Neugierde habe ich Ihren Code mit gcc unter Linux getestet, und er ist robuster als erwartet (schließlich ist das Schreiben von Daten in einen Zeichenpuffer der Länge 0 ein undefiniertes Verhalten ... ich würde erwarte , dass es abstürzt.

Hier ist meine Modifikation Ihres Codes:

%Vor%

Mein erster Gedanke war, dass Sie durch die Tatsache gerettet werden könnten, dass Sie nur Daten an einem einzigen Speicherort lesen - wenn Sie zwei Puffer verwenden, könnte der zweite den ersten überschreiben ... also habe ich den Code in gebrochen Eingabe- und Ausgabeabschnitte:

%Vor%

Wenn der erste Puffer überschrieben worden wäre, würden wir

sehen %Vor%

Das ist also nicht der Fall. [aber das hängt davon ab, wie viele Daten Sie in jeden Puffer packen ... siehe unten]

Dann habe ich eine verrückte Menge an Daten in beide Variablen eingefügt:

%Vor%

(Dies setzt 4+ MB von 'c's in den Kopierpuffer). Ich habe dies sowohl beim ersten als auch beim zweiten Scanf-Aufruf eingefügt. Das Programm hat es ohne Segmentierungsfehler gemacht.

Obwohl ich keinen Segmentierungsfehler hatte, wurde der erste Puffer gelöscht . Ich konnte es nicht sagen, weil so viele Daten über den Bildschirm flogen. Hier ist ein Lauf mit weniger Daten:

%Vor%

Es gab eine kleine Glyphe nach aaaaaaaaaaaa, was bedeutet, dass mein Terminal ein Unicode-Zeichen darstellt, das nicht angezeigt werden kann. Dies ist typisch für überschriebene Daten: Sie wissen nicht, was Ihre Daten überschreibt ... es ist ein undefiniertes Verhalten, so dass Sie anfällig für nasale Dämonen sind.

Die Quintessenz ist, dass Sie mit dem Feuer spielen, wenn Sie in den Speicher schreiben, dem Sie keinen Speicherplatz zugewiesen haben (entweder explizit mit malloc oder implizit mit einem Array). Früher oder später wirst du die Erinnerung überschreiben und dir selbst jede Art von Trauer zufügen.

Die wahre Lektion hier ist, dass C keine Grenzen beim Überprüfen von gibt. Es lässt dich glücklich in die Erinnerung schreiben, die du nicht besitzt. Sie können es den ganzen Tag lang tun. Ihr Programm wird möglicherweise korrekt ausgeführt und es möglicherweise nicht. Es kann zum Absturz kommen, es kann beschädigte Daten zurückschreiben, oder es kann funktionieren, bis Sie ein Byte mehr scannen als während des Tests. Es ist egal, also musst du.

Der Fall von malloc(0) ist einfach ein Sonderfall von diese Frage .

    
Barton Chittenden 21.05.2012 13:35
quelle

Tags und Links