Kadaj Geschrieben 9. Dezember 2011 Geschrieben 9. Dezember 2011 Guten Morgen, ich habe schon wieder einen Speicherzugriffsfehler in einem Programm :/ Das Programm soll einen Pfad als Parameter entgegen nehmen, die extension vom restlichen Namen trennen und im restlichen Namen alle Zeichen, die kein alnum sind bzw kein "-" oder "_" sind, durch "_" ersetzen. Kompilieren funktioniert, aber beim Ausführen bekomme ich einen Speicherzugriffsfehler. Ich habe überall printf-Anweisungen eingebaut, weil ich dachte, ich könnte den Fehler eingrenzen, nun weiß ich dadurch zwar wo der Fehler sein soll, aber nicht wo er herkommt ... Hier erstmal der code: #include <stdio.h> #include <dirent.h> #include <errno.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> typedef struct content //hier stehen die getrennten zeichenketten { char base[64]; char extension[20]; }content; void split( struct content *c, char *a ) //funktion zum trennen { printf("aa"); int i=0, pointpos=0; int lenght=0; int l=0, k=0; lenght=strlen(a); for(l-=1;l>l-20;l--) { printf("a"); if(a[l] == '.') { printf("b"); pointpos=l; while(pointpos<lenght) { c->extension[k]=a[l]; k++; l++; } break; } } for(i=0;i<pointpos;i++) { c->base[i]=a[i]; } c->base[i]=0; } void kill(char *a) { int lenght=0,i=0; lenght=strlen(a); for(i=0; i<lenght; i++) { if(a[i] == '-' || a[i] == '_' || isalnum(a[i])) continue; else { a[i]='_'; } } } int main(int number, char *para[5]) { struct content c; //int a=0; //int i =1; char neu[64]; //int lang=0; DIR *directory; struct dirent *entry; directory = opendir(para[1]); //struct dirent info; while((entry=readdir(directory)) != NULL) { if(strcmp(entry->d_name,".") != 0 && strcmp(entry->d_name,"..") != 0 ) { printf("1\n"); split(&c,entry->d_name); //aufteilen des namen in base und extension printf("2 \n"); kill(c.base); //unzulässige zeichen entfernen printf("3 \n"); strcpy(neu,c.base); //kopieren der base in neu printf("4 \n"); strcat(neu,c.extension); //anfügen der extension an neu printf("5 \n"); if(rename(entry->d_name,neu) == 0) printf("%s umbenannt in %s \n",entry->d_name,neu); else perror("rename"); } } return 0; } [/PHP] und das ist die Ausgabe: [PHP] # ./rename . 1 Speicherzugriffsfehler Kann mir jemand sagen, was ich falsch gemacht hab? Vielen Dank! Zitieren
Klotzkopp Geschrieben 9. Dezember 2011 Geschrieben 9. Dezember 2011 Deine Schleifenvariable l in split läuft von -1 rückwärts. Wenn l kleiner als 0 ist, ist ein Zugriff auf a[l] undefiniert. Die Schleifenbedingung ist auch kaputt. l>l-20 wird erst dann false, nachdem l den kleinstmöglichen Wert für int erreicht hat. Zitieren
Kadaj Geschrieben 9. Dezember 2011 Autor Geschrieben 9. Dezember 2011 Stimmt, das hab ich garnicht gesehen, danke dir! Dass l nicht bei -1 anfangen soll versteh ich (an der Stelle hatte ich lenght erst später hinzugefügt und vergessen es in die Schleife zu nehmen), nur was meinst du mit l>l-20 ? Dass das die einzige Abbruchbedingung ist? Dann würde ich es verstehen, ich hab den Schleifenkopf jetzt geändert: for(l=lenght-1;l>l-20 || l!=1;l--) Aber der Speicherzugriffsfehler ist immernoch da, immerhin wird ja auch nicht "aa" ausgegeben von meiner printf-Anweisung. Also muss doch theoretisch die Übergabe der Variable an split oder die ganze Funktion selbst nicht funktionieren. Oder liege ich da falsch? Zitieren
Hexagon Geschrieben 9. Dezember 2011 Geschrieben 9. Dezember 2011 Moin. Ich bin mir jetzt nicht ganz sicher, aber ist entry->d_name nicht ein char-Array? Zitieren
Klotzkopp Geschrieben 9. Dezember 2011 Geschrieben 9. Dezember 2011 was meinst du mit l>l-20 ?Für welchen Wert von l soll dieser Ausdruck denn jemals false ergeben? Die Schleifenbedingung while(pointpos<lenght)ist auch nicht gut, wenn man bedenkt, dass sich in der Schleife weder pointpos noch lenght ändert. Damit bleibt auch der Wert dieses Ausdrucks immer gleich. Schöne Endlosschleife. Aber der Speicherzugriffsfehler ist immernoch da, immerhin wird ja auch nicht "aa" ausgegeben von meiner printf-Anweisung. Also muss doch theoretisch die Übergabe der Variable an split oder die ganze Funktion selbst nicht funktionieren. Oder liege ich da falsch?Ja, da liegst du falsch. Konsolenausgaben können gepuffert werden. Du könntest fflush(stdout) benutzen, um das Schreiben zu erzwingen. Noch besser wäre natürlich die Verwendung eines Debuggers. Zitieren
Kadaj Geschrieben 9. Dezember 2011 Autor Geschrieben 9. Dezember 2011 Ich bin mir jetzt nicht ganz sicher, aber ist entry->d_name nicht ein char-Array? Also entry ist eine Struktur, die ich selbst definiert habe, vom Typ DIR. Weil ich auf eine Komponente von DIR zugreife, über einen Pointer auf die Komponente d_name zugreife, verwende ich "->". d_name selbst müsste ein char_array sein...ich hoffe, ich hab jetzt keinen Mist geschrieben ^^`` Für welchen Wert von l soll dieser Ausdruck denn jemals false ergeben? Also so, wie ich es jetzt nochmal verändert habe, soll es false ergeben, wenn er die letzten 20 Zeichen des Namen abgearbeitet hat (weil ich einfach festlege, dass es keine extension geben wird, die länger als 19 Zeichen ist) oder, wenn l den wert 1 erreicht (beispiel: "backrezept"; a ist das letzte Zeichen, welches überprüft wird, weil der Punkt ja mindestens an 2. Stelle sein muss z.B.: a."out") Naja, wenn ein Punkt gefunden wird, dann verlasse ich die Schleife einfach mit break, nachdem ich die Position des Punktes gespeichert habe... Es wäre bestimmt sauberer, wenn ich das mit in die Schleifen-Bedingung packe, oder? Die Schleifenbedingung while(pointpos<lenght)ist auch nicht gut, wenn man bedenkt, dass sich in der Schleife weder pointpos noch lenght ändert. Damit bleibt auch der Wert dieses Ausdrucks immer gleich. Schöne Endlosschleife. Wie Recht du hast...:upps Ja, da liegst du falsch. Konsolenausgaben können gepuffert werden. Stimmt ja, nur war mir bisher nie klar, wann das passieren kann. Ist das bei Funktionsaufrufen prinzipiell so, da diese ja ohnehin komplett an die main weitergegeben werden, wenn sie fertig sind? Zitieren
Klotzkopp Geschrieben 9. Dezember 2011 Geschrieben 9. Dezember 2011 Also so, wie ich es jetzt nochmal verändert habe, soll es false ergeben, wenn er die letzten 20 Zeichen des Namen abgearbeitet hat (weil ich einfach festlege, dass es keine extension geben wird, die länger als 19 Zeichen ist) oder, wenn l den wert 1 erreichtWenn l gleich 1 ist, steht da 1>(1-20) also 1>-19 Ist immer noch true. Eine Zahl ist immer größer als dieselbe Zahl um 20 verringert. Das wird erst dann false, wenn du die Grenze des Wertebereichs erreichst, bei einem 32-Bit-int also jenseits der -2 Milliarden. Naja, wenn ein Punkt gefunden wird, dann verlasse ich die Schleife einfach mit break, nachdem ich die Position des Punktes gespeichert habe. .. Es wäre bestimmt sauberer, wenn ich das mit in die Schleifen-Bedingung packe, oder?Du musst in der Schleifenbedingung einfach dafür sorgen, dass l nicht ungültig werden kann. Und bedenke, dass ein Dateiname keinen Punkt enthalten muss. Zitieren
Kadaj Geschrieben 9. Dezember 2011 Autor Geschrieben 9. Dezember 2011 Jaa, jetzt ist der Groschen gefallen, natürlich:upps fflush(stdout); ist ja echt genial, danke für die Hilfe! Jetzt funktioniert split() auch :-) Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.