Anzeige:
Ergebnis 1 bis 10 von 10

Thema: [C] Speicherzugriffsfehler...nur wo?

  1. #1
    Registrierter Benutzer Avatar von SeeksTheMoon
    Registriert seit
    22.02.2002
    Beiträge
    762

    [C] Speicherzugriffsfehler...nur wo?

    Ich schreibe ein C-Programm, das aus einem Verzeichnis alle .xcf-Dateien ausliest und deren Namen ohne Endung in eine Liste schreibt.
    Damit will ich nachher weiterarbeiten.

    Ich hab einen ganz merkwürdigen Fehler: folgender Code funktioniert, wenn man den Testausgaben glauben schenkt:

    Code:
    int maxlaenge=0;
    int laenge=0;
    //für Verzeichnis+Bilderarbeit
    DIR* bildverzeichnis = opendir("Bilder");
    struct dirent* inhalt;
    char** bildliste;
    short listsize=0;
    int i=0;
    
    while ( (inhalt = readdir(bildverzeichnis) ) !=NULL ) {
    	//Alle Gimp-Dateien rauspuhlen und die xcf-Endung kicken
    	if(strstr((const char*)inhalt->d_name,".xcf")!=NULL) {
    		printf("Datei %s ",inhalt->d_name);
    		bildliste[listsize]=(char*)malloc((strlen(inhalt->d_name)-3)*sizeof(char));
    		
    		strcpy(bildliste[listsize],strtok(inhalt->d_name, ".xcf"));
    		
    		//direkt die Länge des Dateinamens fürs eyecandy sichern
    		laenge=strlen((const char*)bildliste[listsize])+4;
    		if(maxlaenge < laenge)
    			maxlaenge=laenge;
    		printf("Länge: %d",maxlaenge);
    		
    		listsize++;
    		printf("Listsize: %d\n",listsize);
    	}
    }
    Sobald ich aber IRGENDEINE Anweisung nach der letzten }-Klammer bringe, also z.B. printf("hallo");, kommt ein Speicherzugriffsfehler.
    Das ist nunmal super-strange, vor allem weil in printf("hallo") gar nicht auf irgendwelche Arrays o.ä zugegriffen wird.

    Was mich auch wundert ist die normale Ausgabe des Programms:

    Code:
         26316:     symbol=strtok;  lookup in file=./make
         26316:     symbol=strtok;  lookup in file=/lib/libc.so.6
         26316:     symbol=strcpy;  lookup in file=./make
         26316:     symbol=strcpy;  lookup in file=/lib/libc.so.6
    Datei Bild1.xcf Länge: 9Listsize: 1
    Datei Bild2.xcf Länge: 9Listsize: 2
    ...
    Speicherzugriffsfehler
    Die ersten 4 Zeilen kommen auch wenn das Programm ohne Zugriffsfehler läuft.
    Also entweder habe ich Mist gemacht, was mich um 2 Uhr nachts nicht wundert oder C hat seit neustem irgendeine ganz dicke Macke.
    Ich behaupte einfach mal ganz dreist, alles richtig gemacht zu haben
    (das Programm heißt make, aber ich rufe es mit ./make auf, so dass keine Verwechselungsgefahr mit gmake besteht)
    Geändert von SeeksTheMoon (21-07-2004 um 08:42 Uhr)
    I haven't lost my mind - It's somewhere on a backup-disc

  2. #2
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Wo legst du Speicher für char** bilderliste an?
    Also nicht nur für die einzelnen Einträge.

    Dann überprüfe nochmal, ob du genug Speicher anlegst für strcpy (auch für das \0 Zeichen), scheint zu passen, aber du kannst das leichter überprüfen.

    Achja, die vielen unnötigen Casts (auch char* bzw. const char), sind ... äh unnötig , und sizeof (char) ist immer 1.

  3. #3
    Registrierter Benutzer Avatar von SeeksTheMoon
    Registriert seit
    22.02.2002
    Beiträge
    762
    der Speicher fürs \0 Zeichen passt scho. Der Speicher für die erste Dimension des Array fehlt allerdings, das ist mir irgendwie auch schon durch den Kopf gegeistert.
    Ich probier das noch schnell aus.

    Wenn ich die casts weglasse, schreibt der Compiler mir die Konsole mit Warnungen voll.
    I haven't lost my mind - It's somewhere on a backup-disc

  4. #4
    Registrierter Benutzer
    Registriert seit
    11.07.2004
    Beiträge
    8
    Zitat Zitat von wraith
    und sizeof (char) ist immer 1.
    Falsch. Ich kenne zwar zugegebenermaßen keinen Compiler, bei dem es nicht so ist, aber mit ein bisschen suchen findet man ganz sicher einen.

  5. #5
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Zitat Zitat von Ringding
    Falsch. Ich kenne zwar zugegebenermaßen keinen Compiler, bei dem es nicht so ist, aber mit ein bisschen suchen findet man ganz sicher einen.
    Falsch, sizeof(char) ist per Definition (laut Standard) 1.Auch wenn char > 8 Bits.
    Hab' jetzt keine Lust den Standard zubemühen, daher muss K&R 2 reichen,
    Seite 198,A.7.4.8
    Wird sizeof auf char angewendet, ist das Resultat 1.

    Wenn du einen Compiler findest, wo das nicht so ist, dann ist der nicht standardkonform.

  6. #6
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Der Cast bei malloc sollte wohl drinbleiben, auch wenn C den nicht fordert. Wenn die Restlichen weggemacht werden, sollte der Compiler eigentlich nicht meckern.

    Das aber nur so am Rande. Eigentlich wollte ich dich darauf hinweisen, das selbst bei diesem kleinen Stück Code recht subtile Speicherfehler auftreten können. Du musst ja für "bilderliste", also nicht nur für die einzelnen Einträge, sondern Platz für die Zeiger auf die Einträge anfordern. Naheliegend wäre es, vor dem Scannen des Verzeichnisses nachzuschauen wieviele Einträge es gibt, und dann den nötigen Platz anzuforden.
    Das reicht aber nicht! Denn zwischen der Speicheranforderung und dem Scannen des Verzeichnisse können ja weitere Dateien hinzukommen! Und dann hast du ein typischen Buffer-Overflow. Also solche Sachen müsstest du beachten.

    Mein Tipp wäre, benutze C++, dann bekommst du Klassen die sich automatisch um ihren Speicher kümmern sozusagen gratis dazu.

  7. #7
    Registrierter Benutzer Avatar von SeeksTheMoon
    Registriert seit
    22.02.2002
    Beiträge
    762
    das hier klappt:
    Code:
    //das Array für einen Eintrag vergrößern
    bildliste=(char**)malloc(sizeof(char*));
    
    while ( (inhalt = readdir(bildverzeichnis) ) !=NULL ) {
    	//Alle Gimp-Dateien rauspuhlen und die xcf-Endung kicken
    	if(strstr((const char*)inhalt->d_name,".xcf")!=NULL) {
    		//das Array um 1 Zeile erweitern
    		listsize++;
    		bildliste=(char**)realloc(bildliste,sizeof(char*)*listsize);
    		
    		//den Eintrag an der aktuellen Stelle im Array vergrößern
    		bildliste[i]=(char*)calloc((strlen(inhalt->d_name)-3),sizeof(char));
    		
    		//Dateinamen bis auf Endung kopieren; \0 wird nicht angehängt, ist
    		//durch calloc aber vorhanden
    		strncpy(bildliste[i],inhalt->d_name, strlen(inhalt->d_name)-4);
    		
    		//direkt die Länge des Dateinamens fürs eyecandy sichern
    		laenge=strlen((const char*)bildliste[i])+4;
    		if(maxlaenge < laenge)
    			maxlaenge=laenge;
    		
    		/*Kontrollausgaben
    		printf("bildliste*= %d\n",listsize);
    		printf("bildliste**= %s,",bildliste[i]);
    		printf("%d Zeichen lang\n",strlen(bildliste[i]));
    		*/
    		i++;
    	}
    }
    Klaro ist C++ komfortabler, ich will aber C
    Während des Verzeichnislesens kommt in dem Verzeichnis nichts an Dateien hinzu und falls doch, so dürfte das bei mir kein Problem darstellen, weil ich direkt für die Dateien die gefunden werden den Speicher anfordere und nicht im voraus.
    I haven't lost my mind - It's somewhere on a backup-disc

  8. #8
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Alle diese Speicheranforderungen können auch schiefgehen. Das testest du nicht. Ist mir erst gar nicht aufgefallen.

  9. #9
    Registrierter Benutzer Avatar von SeeksTheMoon
    Registriert seit
    22.02.2002
    Beiträge
    762
    jo, das mache ich noch.
    I haven't lost my mind - It's somewhere on a backup-disc

  10. #10
    Registrierter Benutzer
    Registriert seit
    11.07.2004
    Beiträge
    8
    Zitat Zitat von wraith
    Falsch, sizeof(char) ist per Definition (laut Standard) 1.Auch wenn char > 8 Bits.
    Hab' jetzt keine Lust den Standard zubemühen, daher muss K&R 2 reichen,
    Seite 198,A.7.4.8
    Wird sizeof auf char angewendet, ist das Resultat 1.
    Tatsächlich, hab grad im C++ Standard (5.3.3)nachgeschaut. Bin jetzt echt überrascht.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •