C strncpy hängt willkürlich Zeichen an

Jurij

Lt. Commander
Registriert
Juni 2008
Beiträge
1.247
Hallo zusammen!

Ich habe folgende Funktion:
Code:
int add(char buffer[], char *namen[])
{
    int i = 0;
    for(i=0; i<86; i++)
    {
        if(strcmp(namen[i], "0") == 0)
        {
            namen[i] = malloc(strlen(buffer));
            printf("%d\n", strlen(buffer));
            strncpy(namen[i], buffer, strlen(buffer));
            return i;
        }
    }
    return -1;
}

Im Grunde sollen dem Array namen Einträge hinzugefügt werden.
Es funktioniert auch so, wie es soll.
Nur bei manchen Einträgen werden einfach irgendwelche Zeichen mit angehängt.
Ich vermute, das es daran liegt, dass das 0 Byte nicht angehängt wird. Daher wird nicht erkannt, wo der String aufhört.

Meine Frage nun, wie kann ich das Problem lösen?
strcpy geht nicht, da die Strings unterschiedlich lang sind, und es so zu Problemen kommt. Ich hab auch schon probiert, ein Zeichen bei strncpy mehr zu kopieren, doch auch hier hängt sich das Programm komplett auf.
Wo liegt mein Fehler?

Danke!
 
Strings in C terminieren mit 0x00. Wer nach "0" sucht, sucht nach 0x30.
 
strlen() gibt dir die Länge eines null-terminierten Strings ohne ohne das Null-Terminierungszeichen selbst. Deshalb ist deine Speicherallozierung in Zeile 8 ein Zeichen zu klein.
Ergänzung ()

P.S. Muß es wirklich C sein? Wenn du stattdessen C++ und die std::string-Klasse verwenden würdest, könntest du dir 'ne Menge Kopfschmerzen ersparen.
 
Ah natürlich, ich Depp.
Ich hatte probiert, bei strncpy ein Zeichen mehr zu kopieren, was natürlich nicht ging, da malloc dann einen Platz zu wenig reserviert hatte. Bei beiden eine +1 dahinter und es geht.

Manchmal sieht man die einfachsten Dinge nicht.
Danke!
 
Ein hübsches Bömbchen hast du da gebaut.
Der Code ist schwer lesbar für Leute die nicht hellsehen können, was wohl auch JennyCB auf das Glatteis führte.

"int add(char buffer[], char *namen[])"
Die Felder werden komplett über den Stack kopiert. Muss das sein?
"add" ist kein Name der die Funktion beschreibt.

"if(strcmp(namen, "0") == 0)"
Heisst das du hast vorher ein Feld aus 86 Adresszeigern erzeugt und auf Speicherbereiche mit '0\0' als Zeichenkette zeigen lassen?
Ernsthaft?

"namen = malloc(strlen(buffer)+1);"
Super, kann klappen, muss aber nicht. Erzeugt im Erfolgsfall einen Zeiger auf einen NEUEN Speicherbereich obwohl du vorher ja einen hattest der auf "0" zeigt. Das ist weder klug noch effektiv. Es sei denn du hattest keinen gültigen Zeiger auf "0" sondern oben schon Mist gebaut.

" strncpy(namen, buffer, strlen(buffer)+1);"
Macht jetzt das gleiche wie "strcpy()", nur komplizierter, denn deine einzige Rettunng ist "strlen()" oben, das aber nur klappt wenn "buffer[]" immer null-terminiert ist und dann funktioniert "strcpy()" natürlich auch.

Wenn du irgendwo "free()" aufrufst dann hast du entweder die zweite Bombe oder vertraust darauf, daß dich das Betriebssystem inmmer rettet, da der erste Zeiger ja von "malloc()" überschrieben wurde.

Ein Tipp: schmeiss die Routine über Board und mach eine kürzere und sichere Fassung.
 
Plaste schrieb:
"int add(char buffer[], char *namen[])"
Die Felder werden komplett über den Stack kopiert. Muss das sein?

Ich stimme dir in allen Punkten zu - außer in diesem. Da werden lediglich 2 Adressen kopiert.
Ergänzung ()

Na ja, in Sachen strcpy() vs strncpy() bin ich dann auch nicht ganz auf deiner Seite. Die Verwendung von strncpy() ist eigentlich zu bevorzugen, aber dann sollte als letzter Parameter auch ( die Größe des Zielpuffers - 1 ) angegeben werden.

http://www.cplusplus.com/reference/cstring/strncpy/

Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.

No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).

P.S. Zur Erläuterung; strcpy() kopiert so lange Zeichen, bis im Quellstring ein \0 gefunden wird. Ist der Quellstring länger als der Zielpuffer, wird einfach gnadenlos über die Puffergrenze hinaus weitergeschrieben. strncpy() hingegen, kopiert nur maximal so viele Zeichen, wie als letzter Parameter angegeben worden ist.
 
Zuletzt bearbeitet:
antred schrieb:
Ich stimme dir in allen Punkten zu - außer in diesem. Da werden lediglich 2 Adressen kopiert.
Verdammt, mit den Feldern war ich mir so sicher :(
Ergänzung ()

Na ja, in Sachen strcpy() vs strncpy() bin ich dann auch nicht ganz auf deiner Seite. Die Verwendung von strncpy() ist eigentlich zu bevorzugen, aber dann sollte als letzter Parameter auch ( die Größe des Zielpuffers - 1 ) angegeben werden.

P.S. Zur Erläuterung; strcpy() kopiert so lange Zeichen, bis im Quellstring ein \0 gefunden wird. Ist der Quellstring länger als der Zielpuffer, wird einfach gnadenlos über die Puffergrenze hinaus weitergeschrieben. strncpy() hingegen, kopiert nur maximal so viele Zeichen, wie als letzter Parameter angegeben worden ist.

Ziel und Quelle sind durch strlen() schon gleich gross, ein überschreiben in den Bereich dahinter ist nicht mehr möglich. Daher ist das Result an dieser Stelle das gleiche, ob nun mit strncpy oder strcpy.
Der Zielpuffer ist nicht initialisiert, ihn mit -1 jetzt anzugeben hieße weniger Daten reinzuschreiben und ihn dann nicht mehr 0-terminiert zu haben. Buffer ist nicht das Ziel sondern die Quelle. Verworren, ich weiss.

Ich hoffe ich habe jetzt keinen zweiten Denkfehler produziert.
 
Plaste schrieb:
Ziel und Quelle sind durch strlen() schon gleich gross, ein überschreiben in den Bereich dahinter ist nicht mehr möglich.

Leider stimmt das nicht. malloc() kann NULL zurück geben und dann ist der Zielpuffer nicht nur ungleich groß, sondern dein Programm stirbt auch an Nullzeigerdereferenzierung. Nicht ganz so schlimm, wie ein Buffer Overflow, aber ich wollte es doch mal angemerkt haben. Wenn eine Funktion in irgend einer Form versagen kann, dann musst du darauf immer prüfen. Auch wenn du glaubst, ach das passiert doch eeeeh nieeee.
 

Ähnliche Themen

Zurück
Oben