closedir führt nach Benutzung von stat zum Absturz
-
Ich möchte nun also den Inhalt eines Verzeichnisses sehen. Dazu kann ich unter Windows und Unix gleichermaßen die in dirent.h definierten Konstrukte benutzen.
Funktioniert auch wunderbar.Vielleicht möchte ich über den Inhalt aber auch etwas genauer Bescheid wissen, z.B. was eine Datei und was ein Unterverzeichnis ist. Wiederum steht unter Windows und Unix gleichermaßen ein Header mit dazu verwendbaren Definitionen zur Verfügung, nämlich sys/stat.h.
Funktioniert auch wunderbar.Aber nun, Wunder über Wunder und keine Kneipe in Sicht, nun muss ich feststellen, dass ich ein einmal geöffnetes Verzeichnis nicht mehr schließen kann, wenn ich den Status eines Inhaltes abgefragt habe:
#include <cstdlib> #include <cstring> #include <dirent.h> #include <sys/stat.h> char * zusammenfuegen(const char * anfang, const char * ende) { char * ergebnis = (char *)malloc(sizeof(char) * (strcspn(anfang, "") + strcspn(ende, "") - 1)); strcpy(ergebnis, anfang); strcat(ergebnis, ende); return ergebnis; } int main() { DIR * verzeichnis = opendir("."); struct dirent * inhalt = readdir(verzeichnis); struct stat * status = (struct stat *)malloc(sizeof(struct stat *)); // stat(zusammenfuegen("./", inhalt->d_name), status); closedir(verzeichnis); }
Sobald man die auskommentierte Zeile aktivierte, stürzte das Programm beim closedir-Aufruf ab. Das ist nun nicht übermäßig tragisch, aber - warum!?
Und was kann ich dagegen tun?Getestet mit aktuellem minGW (gcc-Version 4.5.2) auf Windows 7 Professional SP1 64bit.
-
LordZsar1 schrieb:
Ich möchte nun also den Inhalt eines Verzeichnisses sehen. Dazu kann ich unter Windows und Unix gleichermaßen die in dirent.h definierten Konstrukte benutzen.
dirent.h gibt es nicht mit C Standard, kann aber vom Compiler bereitgestellt werden.
Wiederum steht unter Windows und Unix gleichermaßen ein Header mit dazu verwendbaren Definitionen zur Verfügung, nämlich sys/stat.h.
Wiederum dito.
char * ergebnis = (char *)malloc(sizeof(char) * (strcspn(anfang, "") + strcspn(ende, "") - 1));
Bist du masochistisch veranlagt? Ist der Code in deiner Kneipe entstanden?
Man benutzt strlen für die Ermittlung der Länge eines Strings. Und "-1" ist auch falsch, sollte "+1" heissen.
sizeof(char) ist immer 1, malloc-Caster sind meist verhinderte C++ler, cstdlib lässt ebenso darauf schließen, dass du C mit einem C++ Compiler versuchst, zu übersetzen.
-
Wutz schrieb:
.. Ist der Code in deine Kneipe entstanden? ..
-> in deiner Kneipe.
höflicher: in Deiner Kneipe.Das war die Retourkutsche für den Papagai
-
Höchst erleuchtend. Zur Erheiterung des Klientels: Ja, ich habe wohl strlen übersehen. So etwas kommt sogar in meiner Muttersprache vor, unvorstellbar aber wahr. Leider hat es mit dem Problem so rein gar nichts zu tun.
Um nützliche Informationen zu extrahieren: Ich muss im Compilerforum fragen, ja?
-
Wer lesen kann, ist klar im Vorteil. Hinter dem strlen-Satz steht noch einer.
-
Bitte auch selbst lesen: Das ist völlig egal.
Hier der wutzifizierte Quelltext:
#include <stdlib.h> #include <string.h> #include <dirent.h> #include <sys/stat.h> char * zusammenfuegen(const char * anfang, const char * ende) { char * ergebnis = (char *)malloc(strlen(anfang) + strlen(ende) + 1); strcpy(ergebnis, anfang); strcat(ergebnis, ende); return ergebnis; } int main() { DIR * verzeichnis = opendir("."); struct dirent * inhalt = readdir(verzeichnis); struct stat * status = (struct stat *)malloc(sizeof(struct stat *)); // stat(zusammenfuegen("./", inhalt->d_name), status); closedir(verzeichnis); }
malloc NICHT zu casten, verhindert übrigens das Compilieren.
"error: invalid conversion from 'void *' to 'char *'"
-
Du memoryleak heini!
-
LordZsar1 schrieb:
malloc NICHT zu casten, verhindert übrigens das Compilieren.
Zum zweiten Mal: Du kannst nicht lesen. Dein Aha-Erlebnis folgt vielleicht noch irgendwann.
Gehe davon aus, dass der Compiler immer Recht hat, weder der Compilerbauer noch die Implementierung von stat haben Schuld, ausschließlich dein Code ist Schuld.
Sei froh, dass der Compiler dich auf solche Unzulänglichkeiten in deinem Code durch den Abbruch implizit hinweist, er könnte es auch bleiben lassen.
-
struct stat * status = (struct stat *)malloc(sizeof(struct stat *));
Warum besorgst du dir Platz für einen Pointer auf eine
struct stat
?Den Pointer hast du doch schon mit
status
.
-
Ist es nicht notwendig?
Ich las hier, dass die Funktion an den Ort, an den der Zeiger zeigt, speicherte ("[...] writes it to the area pointed to by the buf argument.") und das sollte dann vielleicht nicht gerade NULL oder undefiniertes Nirvana sein.... Ich kann mir nicht recht vorstellen, warum es so ist, aber wenn ich diese Initialisierung fortlasse, geschieht in der Tat kein Absturz. Höchst verwunderlich. Nun will ich sogleich ausprobieren, ob es auch noch - funktioniert.
-
An der Stelle wo der Zeiger hinzeigt brauchst du dann schon Platz für die ganze struct.
Und das geht auch ohne malloc:struct stat status; stat(zusammenfuegen("./", inhalt->d_name), &status);
oder wenn du unbedingt dynamisch sein willst:
struct stat * status = (struct stat *)malloc(sizeof(struct stat )); // ^ Da ist es anders
-
Ach, ach, ich habe mir schon fast gedacht, dass es so enden würde.
Jawohl, in der Tat, so funktioniert's durchaus.... Ganz ohne Initialisierung ebenfalls, aber dann stürzt mein "echtes" (d.h. nicht mal schnell zusammengeschnipseltes Vorführ-) Programm beim Rücksprung ab.
Ich gehe daher davon aus, dass der struct durchaus bereitgestellt werden muss - aber natürlich auch in voller Länge (oh, dämliches Mensch, das ich bin).Sei wohl bedankt, DirkB, hier einzig Hilfreicher und dann gar Problemerschöpfender.
-
dein code leakt