2016-05-06 8 views
1

Was im Interesse ist dies ist.Uninitialized Wert wurde von einer Heap-Zuweisung erstellt, wenn ich nicht memset

Grundsätzlich im obigen Beispiel bekomme ich Fehler, dass nicht initialisierte Wert von einer Heap-Zuweisung erstellt wurde. Aber wenn ich folgendes Ding mache und memset() zwischen malloc() und if statement einfüge, sehe ich den gleichen Fehler nicht. Ich würde gerne einige Vorschläge hören, ist das der richtige Weg, wenn nicht, was ist richtig?

char *assign_value = (char*)malloc(10 * sizeof(char)); 
memset(assign_value, 0, sizeof(assign_value)); 
if(strlen(assign_value) == 0) { 
    strcpy(assign_value, "A"); 
} else { 
    strcat(assign_value, "A"); 
} 

Dank!

+1

'malloc' nie initialisieren oder auf Null setzen. Wenn Sie möchten, können Sie mit "memset" danach gehen oder "calloc" verwenden. – ameyCU

Antwort

2

Das Problem kommt aus dem Aufruf strlen(assign_value), wenn assign_value nicht initialisiert ist, wie von malloc(10) zurückgegeben.

Hier sind drei Möglichkeiten, um fix das Problem:

  • Sie manuell alle Bytes des Arrays mit memset(assign_value, 0, 10); einstellen. Beachten Sie, dass Ihr Aufruf falsch ist, da sizeof(assign_value) auf die Größe des Zeigers, nicht der Größe des Arrays ausgewertet wird.

  • können Sie das Array mit calloc(10, sizeof(char)) zuweisen.calloc gibt die Adresse eines Speicherblocks zurück, der auf alle Bits Null initialisiert wurde. Dies hat den gleichen Effekt wie der Aufruf von memset, ist aber möglicherweise effizienter.

  • Sie können das initiale Byte auf '\0' setzen, um das Array zu einer leeren Zeichenfolge zu machen, die sowohl für die Verwendung mit strcpy als auch für gültig ist.

Mit calloc() statt malloc() ist eine gute Gewohnheit unvorhersehbares Verhalten zu vermeiden, wenn Sie vor dem Gebrauch eines oder alle der zugeordneten Daten zu initialisieren scheitern.

Beachten Sie, dass Ihr Code radikal vereinfacht werden: Wenn der Ziel-String tatsächlich leer ist, ruft strcat()ist entspricht strcpy(). Sie können einfach schreiben:

char *assign_value = calloc(10, sizeof(char)); 
... 
strcat(assign_value, "A"); 

Darüber hinaus sollten Sie überprüfen, ob strcat() nicht einen Pufferüberlauf verursachen, indem sie die Länge der Zeichenfolge Überprüfung bereits in dem Puffer gespeichert:

char *assign_value = calloc(10, sizeof(char)); 
... 
if (strlen(assign_value) < 10 - 1) { 
    strcat(assign_value, "A"); 
} else { 
    // handle the error: not enough space in assign_value 
} 
+0

Danke für die Antwort, ich habe heute etwas Neues gelernt. Schöne Antwort –

1

Ja, Speicher, den Sie von malloc zurückbekommen, ist nicht initialisiert. Im Allgemeinen enthält es unvorhersehbare, zufällige Werte. Zufällig könnten die Zufallswerte 0 sein - aber darauf kann man überhaupt nicht zählen.

Also, ja, wenn Sie sich interessieren, müssen Sie immer den Speicher initialisieren, den Sie von malloc zurückbekommen. Ein Weg ist, indem Sie memset aufrufen - obwohl das von Ihnen gepostete Beispiel ungewöhnlich ist. Wenn Sie den gesamten Speicher auf Null wollen bekam man nur zurück, würde die übliche Anruf sein

memset(assign_value, 0, 10); 

(statt malloc, können Sie auch calloc verwenden. Sobald Unterschied zwischen malloc und calloc ist, dass calloc automatisch die nicht initialisiert werden neu zugewiesener Speicher für alle 0.)

Wenn Sie assign_value als Zeichenfolge verwenden und Sie möchten, dass sie als leere Zeichenfolge beginnt, müssen Sie nicht alles auf Null setzen. Es ist nur ausreichend, um ein Null-Zeichen in der ersten Position zu setzen:

*assign_value = '\0'; 

Sobald Sie all diese Dinge tun, assign_value wird eine leere Zeichenfolge halten, mit einer Länge von 0, so dass der Test if(strlen(assign_value) == 0) immer erfolgreich, und In Ihrem späteren Code rufen Sie immer strcpy, niemals strcat.

Schließlich müssen Sie als Seitenpunkte nicht mit sizeof(char) multiplizieren oder das Ergebnis umwandeln, wenn Sie malloc aufrufen. So könnten Sie die einfachere:

char *assign_value = malloc(10); 

(Sie müssen nicht vermehren sich durch sizeof(char) weil sizeof(char) ist per Definition immer genau 1. Sie haben nicht ausdrücklich das Ergebnis der malloc in C zu werfen, und wenn Sie dies tun, kann es Fehler verbergen.)

0

malloc() reserviert Speicher aber tut initialisiere es nicht. Was auch immer an dem zugewiesenen Speicherplatz zu finden ist, ist was du bekommst. So
wenn malloc verwendet, ist es am besten, um den Puffer zu erstellen und initialisieren:

char *assign_value; 
assign_value = malloc(10 * sizeof(char)); 
memset(assign_value, 0, 10); 

calloc() auf der anderen Seite weist Speicher und initialisiert alle zugewiesenen Standorte 0:

char *assign_value = calloc (10,1);//note sizeof(char) is always 1 

Für mehr lesen, hier ist eine Diskussion comparing malloc() and calloc().

Beachten Sie, dass es nicht erforderlich ist, die Ausgabe von [m] [c] alloc in C wie in C++ zu konvertieren.

Verwandte Themen