Speicherzugriffsfehler in "while" mit EOF Abfrage



  • Hallo,

    ich habe mal wieder einen Speicherzugriffsfehler.
    Compiler: gcc
    Folgender Code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "header.h"                                            //Eigener Header
    
    tag * createlist(char * path)                                  //Typ "tag" von eigener Struktur
    {
    	FILE * fp;
    	tag * firstptr;
    	tag * ptr = malloc(sizeof (tag));
    	long int counter = 0;                                  //"counter" dient für "fseek()"
    	int lv;
    	char c;
    	char temp[64];
    
    	firstptr = ptr;
    
    	if ((fp = fopen("../lists/indir.txt", "r")) == NULL)       //Datei öffnen inkl. Fehlerbehandlung
    	{
    		fprintf(stderr, "\nDatei \"indir.txt\" konnte nicht geoeffnet werden");
    
    		return 0;
    	}
    
    	rewind(fp);
    
    	while ((c = fgetc(fp)) != 10)                              //Zeichenanzahl für erste Zeile ermitteln
    	{
    		counter++;
    	}
    
    	while((c = fgetc(fp)) != EOF)                            //Das Problem geht los
    	{
    		if (c == 'd')                                    //(1)
    		{
    			while(c = fgetc(fp) != 10)
    				counter++;
    		}
    
    		counter = counter+53;
    
    		if ((fseek(fp, counter, SEEK_SET)) != 0)
    		{
    			fprintf(stderr, "\nFehler beim Positionieren des Zeigers");
    		}
    
    		for (lv = 0; (c = fgetc(fp)) != '\n'; lv++)
    		{
    			temp[lv] = c;
    			counter++;
    		}
    
    		temp[lv] = '\0';
    
    		if(temp[lv-4] == '.' && (temp[lv-3] == 'm' || 'M') && (temp[lv-2] == 'p' || 'P') && temp[lv-1] == '3')     //(2)
    		{
    			strcpy(ptr->filename, temp);
    			gettags(path, ptr);                    //Eigene Fkt, Beschreibung unten
    
    			ptr->listptr = malloc(sizeof(tag));
    			ptr = ptr->listptr;
    		}
    	}
    
            printf("\ncheckpoint");
    
    	fclose(fp);
    
    	ptr->listptr = NULL;
    	ptr = firstptr;
    
    /*	while (ptr->listptr != NULL)                         //(3)
    	{
    		printf("\n%s", ptr->filename);
    
    		ptr = ptr->listptr;
    	}*/
    
    	return firstptr;
    }
    

    Das Problem beginnt an der markierten Stelle. Die Funktion createlist() bekommt einen Pfad übergeben, von dem der Inhalt ausgelesen wurde und in "../lists/indir.txt" steht. Nun sollen nur die mp3's aus dieser Datei ausgelesen werden und daraus eine verkettete Liste erstellt werden. Die erste Zeile der Text-Datei wird überzählt, da es für diesen Zweck ungebräuchliche Infos hat. Die Abfrage an der Stelle (1) dient zur Überprüfung ob es sich um ein Ordnder handelt. Die Abfrage an der Stelle (2) ob es sich um 'ne mp3 handelt.
    Die Fkt. gettags() (Rückgabewert: void) macht vorerst nix als den Pfad und den Dateinamen auszugeben. Natürlich ist das für was anderes bestimmt.

    Das "checkpoint" wird nicht mehr ausgegeben. Es werden auch nicht alle Dateien ausgegeben. Davor kommt ein Speicherzugriffsfehler. Also ist der Fehler in der Schleife.

    Komisch ist nur, das bevor ich die Fkt. gettags() eingefügt habe, habe ich das mit dem an der Stelle (3) gecodetem ausgegeben, also nur den Dateinamen. Und es lief einwandfrei. Wenn ich eine andere Abfrage an der Stelle, wo das Problem beginnt, mache, z.B. mit einem "int < 2" beendet das Programm die Schleife auch erfolgreich. Da denke ich, dass irgendwas mit meinem EOF passiert ist. Kann das sein? Wenn ja, was ist mit meinem EOF passiert? Und wie kann man das Problem beheben?
    Ich bedanke mich für Eure Mühe.



  • Ich habe noch vergessen, zu sagen, dass auch wenn ich das auf das ursprüngliche zurückschreibe (auch die Headerdatei), funktioniert es trotzdem nicht mehr. Entweder fällt mir nicht mehr ein, was ich noch geändert hatte, oder es ist mir ein Rätsel wieso es mal einwandfrei funktionierte und nur weil ich 'ne Fkt. eigefügt habe plötzlich nicht mehr.



  • Innerhalb einer EOF while-Schleife fseek aufrufen, irgendwelche Positionen mitzählen, setzen und sich dann wundern, dass das Ende nicht erreicht wird?
    Warum benutzt du nicht die Standardbibliotheksfunktionen zum zeilenweise Lesen wie:

    char zeile[1000];
    ...
    while( fgets(zeile,1000,f) )
      if( strchr(zeile,'.') && !strcmp(strrchr(zeile,'.'),".mp3\n") )
        puts( zeile );
    ...
    


  • also, ich habe das nun mit deinem Algorithmus gelöst.
    Die Fkts. strchr() und strrchr() kannte ich nicht, da habe ich mich nun schlau gemacht.
    Die ersten 53 Zeichen brauche ich nicht. Deswegen habe ich das so umstrukturiert:

    while(fgets(zeile, 256, fp))
    	{
    		if(strchr(zeile, '.') && !strcmp(strrchr(zeile, '.'), ".mp3\n"))
    		{
    			for(lv = 0; zeile[lv+52] != '\n'; lv++)
    			{
    				temp[lv] = zeile[lv+52];
    			}
    
    			temp[lv]= '\0';
    
    			puts(temp);
              }
           }
    

    Die ersten paar gibt er ganz gut aus, bis es dann wieder zu einem Speicherzugriffsfehler gelangt.
    Weisst du außerdem, wieso mein Algorithmus davor mal funktioniert hat?



  • Ouh, sry,

    war wegen zu wenig Platz im temp[] .

    Danke für deine schnelle Hilfe.



  • Nein, weiß ich nicht. Es ist aber eine Eigenart von Fehlern, dass sie nicht immer und nicht immer in gleicher Weise auftreten.
    Du solltest dir den Speicherzugriffsfehler genauer anschauen, oft greift man wegen falscher Indexe auf undefinierte Speicherbereiche zu.
    Warum benutzt du eigentlich nicht die Funktion "popen"? Ist zwar kein Standard, eignet sich für deinen Anwendungsfall aber sehr gut und ersetzt deinen Umweg über eine externe Hilfsdatei vollständig.



  • Die Funktion habe ich auch nicht gekannt. Ich wollte eigentlich den Umgang mit externe Dateien lernen. Wie der Code oben vermuten lässt, folgt jetzt das auslesen der ID3-Tags, wofür ich das brauche. Danach sogar das Bearbeiten davon. Aber es hört sich interessant an, 'werde ich auch mal schlau machen.
    Wie schaut's denn aus mit der Portabilität mit solchen nicht-Standard-Funktionen? Welche Probleme können denn dadurch entstehen?



  • Tja da fragt doch jemand hier außer mir nach Portabilität;
    popen ist POSIX 2001 Standard, sollte also auf jedem gängigen Unix-System vorhanden sein, wird auch von MSVC unterstützt, siehe:

    http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=DE-DE&k=k(POPEN)

    Du siehst, statt des Filedeskriptors einfach den Pipedeskriptor nehmen, fgets arbeitet auch damit in gleicher Weise.


Anmelden zum Antworten