13 Stimmen

Uninitialisierter Wert wurde durch eine Heap-Zuweisung erstellt

Ich habe diesen Fehler verfolgt, aber ich verstehe ihn einfach nicht. Habe ich einige grundlegende C oder etwas vergessen?

==28357== Conditional jump or move depends on uninitialised value(s)
==28357==    at 0x4C261E8: strlen (mc_replace_strmem.c:275)
==28357==    by 0x4E9280A: puts (ioputs.c:36)
==28357==    by 0x400C21: handlePath (myshell.c:105)
==28357==    by 0x400B17: handleInput (myshell.c:69)
==28357==    by 0x400AAD: acceptInput (myshell.c:60)
==28357==    by 0x4009CF: main (myshell.c:33)
==28357==  Uninitialised value was created by a heap allocation
==28357==    at 0x4C25153: malloc (vg_replace_malloc.c:195)
==28357==    by 0x400BDE: handlePath (myshell.c:99)
==28357==    by 0x400B17: handleInput (myshell.c:69)
==28357==    by 0x400AAD: acceptInput (myshell.c:60)
==28357==    by 0x4009CF: main (myshell.c:33)
==28357==

(095) void handlePath(char *input) {
(096)     if(DEBUG_ON) { printf("%s%s\n", "DEBUG_HANDLEPATH: ", input); }
(097)
(098)     char *inputCopy = NULL;
(099)     inputCopy = (char *)malloc((strlen(input)+1)*sizeof(char));
(100)
(101)     if(inputCopy==NULL) {
(102)         die("malloc() failed in handlePath()");
(103)     }
(104)     strncpy(inputCopy, input, strlen(input)*sizeof(char));
(105)     printf("%s\n", inputCopy);
(106)     free(inputCopy);
(107)     return;
(108) }

Zeile 96 gibt den Parameter "char *input" problemlos aus (DEBUG_ON==1), aber Zeile 105 spuckt valgrind-Fehler aus (in der Konsole wird er jedoch problemlos ausgegeben). "char *input" stammt von einem getline(), das eine Eingabezeile abgreift, und ist im Fall dieser Funktion etwas wie "path /test/path" ohne Anführungszeichen. Ich kann es in den vorhergehenden Funktionen problemlos ausgeben und bearbeiten. Was ist an "char *inputCopy" uninitialisiert? Irgendwelche Ideen? Vielen Dank im Voraus!

13voto

John Knoeller Punkte 32285

Sie haben zwei Fehler in Zeile 104,

strncpy(inputCopy, input, strlen(input)*sizeof(char));

Sie müssen strncpy Platz für die abschließende Null geben, also sollte es sein strlen(input)+1 strncpy garantiert nicht, dass der Ausgabepuffer nullterminiert bleibt, was wie ein Fehler in strncpy aussieht, es aber nicht ist. Es wurde so entworfen, dass es auf diese Weise funktioniert. Was strncpy tun sollte, war, eine Zeichenkette in einen Ausgabepuffer zu kopieren und dann den Rest des Puffers mit Nullen füllen ., Es ist nicht wirklich als "sicheres strcpy" konzipiert.

Ihr anderer Fehler ist, dass strncpy eine Zeichen Zählung und nicht eine Byte-Zählung, also ist es falsch, mit sizeof(char). . Da sizeof(char) == 1, ist dies nicht wirklich Probleme verursachen, aber es ist immer noch die falsche Absicht.

Es war richtig, dass Sie mit sizeof(char) im malloc in Zeile 99 seit malloc benötigt eine Byte-Zählung.

4voto

R Samuel Klatchko Punkte 72641

Strncpy setzt kein abschließendes 0-Zeichen, da es höchstens N Zeichen kopiert (wobei N der Parameter 3 ist). Da Sie die Länge angegeben haben und die +1 für die abschließende 0 nicht einbezogen haben, wurde sie nicht hinzugefügt.

Also angenommen, Sie haben einen Puffer von N Bytes, die richtige Verwendung von strncpy ist dies:

strncpy(dest, src, N - 1);
dest[N - 1] = '\0';

strncpy ist eine seltsame Funktion. Abgesehen davon, dass sie nicht verspricht, eine abschließende 0 zu schreiben, wird sie immer genau N Zeichen in den Zielpuffer schreiben. Wenn src kleiner als N ist, nimmt sich strncpy die Zeit, den gesamten Rest des Puffers mit 0en zu füllen.

3voto

Mark Ransom Punkte 283960

Ich glaube, Ihr strncpy setzt kein abschließendes Null-Zeichen an das Ende der Zeichenkette, so dass printf über das Ende des zugewiesenen Speichers hinausläuft.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X