Warum wird diese Zeichenkette überschrieben?
-
Hallo,
ich bin gerade dabei ein kleines Programm zu schreiben, dass von stdin oder von einer Datei daten einließt und diese primitiv "komprimiert". Aber anscheinend mach ich irgendwas mit der Speicherverwaltung falsch, weshalb bei mir ein String komischerweise in einem Fall überschrieben wird, im anderen aber nicht....
Hier mal der Source:#define FILE_EXTENSION ".comp" #define STDIN_FILENAME "Stdin" void compressFile(const char *nameIn) { int oldChar, newChar, countSameChar, uncompressedLen, compressedLen; FILE *fpIn, *fpOutput; char *nameOutput; /* ================= Copy Name for Outputfile ================= */ nameOutput = malloc(sizeof nameIn + sizeof(char)*strlen(FILE_EXTENSION)); if(nameOutput == NULL) { printError(); } /* ================= Get Streams for Input/Output ================= */ fpIn = (strcmp(nameIn,STDIN_FILENAME) == 0) ? stdin : fopen(nameIn,"r"); if(fpIn == NULL) { printError(); } strcpy(nameOutput,nameIn); strcat(nameOutput, FILE_EXTENSION); fpOutput = fopen(nameOutput, "w"); if(fpOutput == NULL) { printError(); } ........ printf("%s:\t\t%d Zeichen\n", nameIn, uncompressedLen); printf("%s:\t\t%d Zeichen\n", nameOutput, compressedLen);
Sooo, wenn ich jetzt das Programm starte, kommt folgendes:
test.txt: 8 Zeichen
test.txt.comp: 16 ZeichenUnd jetzt, wenn ich bisschen was im Quellcode verschiebe:
#define FILE_EXTENSION ".comp" #define STDIN_FILENAME "Stdin" void compressFile(const char *nameIn) { int oldChar, newChar, countSameChar, uncompressedLen, compressedLen; FILE *fpIn, *fpOutput; char *nameOutput; /* ================= Copy Name for Outputfile ================= */ nameOutput = malloc(sizeof nameIn + sizeof(char)*strlen(FILE_EXTENSION)); if(nameOutput == NULL) { printError(); } strcpy(nameOutput,nameIn); strcat(nameOutput, FILE_EXTENSION); /* ================= Get Streams for Input/Output ================= */ fpIn = (strcmp(nameIn,STDIN_FILENAME) == 0) ? stdin : fopen(nameIn,"r"); if(fpIn == NULL) { printError(); } fpOutput = fopen(nameOutput, "w"); if(fpOutput == NULL) { printError(); } ........ printf("%s:\t\t%d Zeichen\n", nameIn, uncompressedLen); printf("%s:\t\t%d Zeichen\n", nameOutput, compressedLen);
Hier der Output:
test.txt: 8 Zeichen
test.txt.comi: 16 ZeichenDas heißt, dass wenn ich das Kopieren des Dateinamens vor dem festlegen von fpIn mache, wird er überschrieben! Wenn ich es danach mache, nicht. D.h. ich schließe daraus, dass ich mit der zuweisung von fpIn bei mir meine Variable nameOutput überschreibe. Aber warum?! Es tritt hier der Fall ein, dass fopen() aufgerufen wird.
Ist das, weil ich meinen Speicher für fpIn und fpOutput mit malloc geholt habe?! Oder ist das, dass ich in der define direktive keine Nullbyteterminierung habe (???) oder weil ich bei meinem malloc bei nameOutput nicht +1 für das Nullbyte geschrieben habe? Wenn ich strcat aufrufe, wird danach der String überhaupt Nullterminiert?
Ich bin gerade etwas verwirrt, wäre echt nett, wenn mir das mal jemand erklären könnte....
Is mein erstes Beispiel in C, programmiere sonst immer in java und da gibt es eben dieses malloc nicht...
Danke schonmal Leute
-
Bist du dir sicher, dass du in Zeile 11 die Größe eines char* wissen willst (sizeof nameIn) oder doch lieber die Länge des Strings?
-
Öhm?
sizeof nameIngibt mir nicht die Größe des Inhaltes an?! Ok, das wäre eine erklärung....
D.h. ich müsste da auch sizeof(char)*strlen(nameIn) machen? (bzw. könnte das sizeof(char) weglassen, weils eh 1 ist....)Könnte ich nicht sizeof *nameIn machen? Dann würde das Dereferenziert werden und dann die wirkliche Größe erhalten? Oder geht das alles mit sizeof nicht?
Danke schonmal
-
sizeof funktioniert nur zur Compilezeit und kann im Programm nicht dynamisch verwendet werden.
-
Zudem brauchst du noch Platz für die/das '\0'.
nameOutput = malloc((strlen(nameIn) + strlen(FILE_EXTENSION) + 1) * sizeof(char) );
-
Noch eine Anmerkung:
sizeof(FILE_EXTENSION) liefert hier 6 (5 Zeichen + '\0') weil es als char[] im aktuellen Scope definiert wird.
strlen(FILE_EXTENSION) liefert hier 5 (5 Zeichen)sizeof nameIn liefert 4 weil es ein Pointer (char*) ist. (Auf 32-Bit Systemen)
Und natürlich terminiert strcat.
-
DirkB schrieb:
nameOutput = malloc((strlen(nameIn) + strlen(FILE_EXTENSION) + 1) * sizeof(char) );
Wieviel Byte groß ist denn sizeof(char) gewöhnlich (garantiert)?
-
_Falke schrieb:
Wieviel Byte groß ist denn sizeof(char) gewöhnlich (garantiert)?
sizeof(char) ist 1. Immer. Denn die Maßeinheit von sizeof sind char-Größen. Und gewöhnlich nennt man das dann auch 1 Byte, aber deine Definition von Byte könnte eine andere sein. Jedenfalls hat ein char nicht zwangsläufig 8 Bit Informationsgehalt (aber mindestens!).
-
_Falke schrieb:
Wieviel Byte groß ist denn sizeof(char) gewöhnlich (garantiert)?
signed char - 1 byte (Bereich -128 ... +127)
unsigned char - 1 byte (Bereich 0 ... 255)sizeof char sollte immer 1 Byte betragen.
[EDIT: Sepp war schneller
]
-
Hallooo, ich wollte damit eigentlich nur sagen, dass die Multiplikation mit sizeof(char) überflüssig ist.
-
_Falke schrieb:
Hallooo, ich wollte damit eigentlich nur sagen, dass die Multiplikation mit sizeof(char) überflüssig ist.
Ahh, ok. Leider kann man rhetorisch ausgesprochene Fragen nicht hören, wenn man sie nur liest.
-
SeppJ schrieb:
Ahh, ok. Leider kann man rhetorisch ausgesprochene Fragen nicht hören, wenn man sie nur liest.
Du kannst also nicht rhetorische ausgesprochene Fragen hören, die du liest?
Hört sich nach einer Inselbegabung an.