Probleme beim Auslesen einer Datei



  • hartmut1164 schrieb:

    Reallocs koennen auch vermieden werden:

    ist ja keine kunst, wenn man mit festen längen arbeitet, wie mit deinem MAX_PATH_LEN.
    🙂



  • hartmut1164 schrieb:

    ...

    Hat es einen Grund, dass Du allokierte Ressourcen im Fehlerfall nicht wieder frei gibst?



  • Tachyon schrieb:

    hartmut1164 schrieb:

    ...

    Hat es einen Grund, dass Du allokierte Ressourcen im Fehlerfall nicht wieder frei gibst?

    Ich benutze ein abort () - das hat etwas die gleiche Wirkung SIGKILL; da wird freigeben. Da passiert aber nur, wenn kein neuer Heap mehr allociert werden kann.



  • +fricky schrieb:

    hartmut1164 schrieb:

    Reallocs koennen auch vermieden werden:

    ist ja keine kunst, wenn man mit festen längen arbeitet, wie mit deinem MAX_PATH_LEN.
    🙂

    MAX_PATH_LEN begrenzt nur die Laenge des Einlesestrings aus dem File. Der String selber wird hier allociert:

    pReturn->szLine = calloc (strlen (szLine) + 1, sizeof (char));
    


  • hartmut1164 schrieb:

    Tachyon schrieb:

    hartmut1164 schrieb:

    ...

    Hat es einen Grund, dass Du allokierte Ressourcen im Fehlerfall nicht wieder frei gibst?

    Ich benutze ein abort () - das hat etwas die gleiche Wirkung SIGKILL; da wird freigeben.....

    Wie kommst Du auf die abstruse Idee? Da wird nichts freigegeben, es sei denn, das OS oder die Implentierung des Compilers tut das rein zufällig. Da kann und sollte man sich aber nicht drauf verlassen.
    Einen Heap gibts in C btw. nicht. Und was soll SIGKILL sein? Du meinst sicher SIGABRT.



  • Tachyon schrieb:

    Ich benutze ein abort () - das hat etwas die gleiche Wirkung SIGKILL; da wird freigeben.....

    Wie kommst Du auf die abstruse Idee? Da wird nichts freigegeben, es sei denn, das OS oder die Implentierung des Compilers tut das rein zufällig. Da kann und sollte man sich aber nicht drauf verlassen.[/quote]

    Gebe zu, abort () erzeugt nicht SIGKILL, sondern SIGABRT. Wenn das OS aus irgentwelchen Gruenden keinen Speicher mehr zur Verfuegung stellen kann (z. B. malloc nicht mehr funktioniert), passiert etwas ziemlich uebles. In diesen Falle tut man gut daran das Programm zu schnell und brutal als moeglich zu beenden. Der Vorteil des abort () ist dabei, dass es einen Core schreibt, den man auswerten kann; was bei einer solchen Fehlfunktion sehr sinnvoll ist.

    Edit: Der Hauptunterschied zwischen SIGKIL und SIGABRT ist, dass eine nicht vom Prozess selber abgefangen werden kann, was aber nicht noetig ist, da SIGABRT vom Prozess selber geworfen wird.

    Tachyon schrieb:

    Einen Heap gibts in C btw. nicht.

    Acht und wo stehen in beiden Beipielen meine 100'000 chars?

    char   szLine_0 [100000];
    char  *szLine_1;
    
    szLine_1 = calloc (100000, sizeof (char));
    

    Bei szLine_0 stehen im Stack und werden bei der Beendigung des Block wieder freigeben, bei szLine_1 steht nur erste Adresse auf den allocierten Bereich im Stack, waerend die 100'000 char in Heap stehen, d. h. die der Speicherplatz der Adresse wird bei der Beendigung des Blocks wieder freigeben, nicht aber der Bereich im Heap, auf den diese zeigt - weshalb man das ganze in den meisten Faellen auch macht.



  • hartmut1164 schrieb:

    In diesen Falle tut man gut daran das Programm zu schnell und brutal als moeglich zu beenden.

    Aber nicht, ohne vorher erfolgreich angeforderte Ressourcen wieder freizugeben.
    Wenn Du ein OS hast (vielleicht gibt es auch kein OS), welches einem nicht hinterher räumt, bekommt man sonst recht schnell Probleme. Und je nach Ressource kann es auch sein, dass selbst das OS nichts machen kann.
    Und ob "was ziemlich Übles" passiert, wenn kein Speicher mehr zur Verfügung steht, hängt stark vom Programm ab. Erstmal schlagen einfach Anforderungen fehl. Das ist so erstmal kein Grund für einen abort.

    hartmut1164 schrieb:

    Edit: Der Hauptunterschied zwischen SIGKIL und SIGABRT ist, dass eine nicht vom Prozess selber abgefangen werden kann, was aber nicht noetig ist, da SIGABRT vom Prozess selber geworfen wird.

    SIGKILL gibt es gar nicht. Es gibt höchstens SIGTERM.

    hartmut1164 schrieb:

    Tachyon schrieb:

    Einen Heap gibts in C btw. nicht.

    Acht und wo stehen in beiden Beipielen meine 100'000 chars?

    In 'nem Speicher mit Allocated Storage Duration. Heaps und Stacks gibt es im C-Standard nicht wirklich, weil dort ziemlich konkrete Datenmodelle hinterstehen.



  • Tachyon schrieb:

    hartmut1164 schrieb:

    In diesen Falle tut man gut daran das Programm zu schnell und brutal als moeglich zu beenden.

    Aber nicht, ohne vorher erfolgreich angeforderte Ressourcen wieder freizugeben.
    Wenn Du ein OS hast (vielleicht gibt es auch kein OS), welches einem nicht hinterher räumt, bekommt man sonst recht schnell Probleme. Und je nach Ressource kann es auch sein, dass selbst das OS nichts machen kann.

    Es gehoert seit dem IBM/360 zu grundlegenden Aufgaben eines OS die Allocierung von Resourcen durch Prozesse zu steuern, sich diese Resourcen "zu merken" und diese ggf. wieder freizugeben.

    Das mag bei der Kernel-Prg. anders sein, aber das ist eher "Randbereich - wenn auch ein extrem wichtiger.

    Tachyon schrieb:

    Und ob "was ziemlich Übles" passiert, wenn kein Speicher mehr zur Verfügung steht, hängt stark vom Programm ab. Erstmal schlagen einfach Anforderungen fehl. Das ist so erstmal kein Grund für einen abort.

    Ich saehe nur zwei Szenarien, wo ich das nicht machen wuerde:

    1. Bei extrem beschraeckten Resourcen (z. B. im embedded Bereich)
    2. Bei sehr grossen angeforderten Datenmengen

    Selbst bei heutigen Feld-Wald-und-Wiesen-Rechnern mit nahezu unbegrenzten Resourcen im Arbeitsspeicher von 100/1000en von MB erscheint mit Szenario 2) in den meisten Faellen wirklich unwahrscheinlich (gibt auch Ausnahmen, aber das sind Ausnahmen).

    Tachyon schrieb:

    SIGKILL gibt es gar nicht. Es gibt höchstens SIGTERM.

    Steht im Posix-std.; ist bei Linux Signal 9

    Tachyon schrieb:

    Einen Heap gibts in C btw. nicht.

    hartmut1164 schrieb:

    Acht und wo stehen in beiden Beipielen meine 100'000 chars?

    In 'nem Speicher mit Allocated Storage Duration. Heaps und Stacks gibt es im C-Standard nicht wirklich, weil dort ziemlich konkrete Datenmodelle hinterstehen.[/quote]

    Das ergibt sich aus der praktischen Implementation als sequenzielle Abarbeitung der localen Variablen (und Uebergabeattribute) und der dynamischen Verwaltung des z.B. ueber malloc allocierten Speichers. Ich will nicht bezweifeln, dass man das auch anders implementieren kann (heap/Stack), wuesste aber nicht wie.



  • hartmut1164 schrieb:

    Es gehoert seit dem IBM/360 zu grundlegenden Aufgaben eines OS die Allocierung von Resourcen durch Prozesse zu steuern, sich diese Resourcen "zu merken" und diese ggf. wieder freizugeben.

    Was ist mit µC, DSPs etc.? Die haben i.d.R. kein OS, das Dir hinterher räumt. Solche Plattformen werden recht oft benutzt und sind weder ein Randbereich noch sonderlich exotisch.
    Selbst unter Windows gibt es einige Ressourcen, die nicht wieder freigegeben werden, wenn der zugehörige Prozess stirbt. Einige GDC-Handles z.B.

    hartmut1164 schrieb:

    Steht im Posix-std.; ist bei Linux Signal 9

    Und was hat Posix mit ANSI-C zu tun?

    hartmut1164 schrieb:

    Ich will nicht bezweifeln, dass man das auch anders implementieren kann (heap/Stack), wuesste aber nicht wie.

    Das glaube ich Dir sofort. 😉



  • Tachyon schrieb:

    Selbst unter Windows gibt es einige Ressourcen, die nicht wieder freigegeben werden, wenn der zugehörige Prozess stirbt. Einige GDC-Handles z.B.

    meinste GDI-handles? das war mal zur zeit der 16-bit windosen, win98, win-me und so. die nt-abkömmlinge räumen alles sauber wieder weg.
    🙂



  • +fricky schrieb:

    Tachyon schrieb:

    Selbst unter Windows gibt es einige Ressourcen, die nicht wieder freigegeben werden, wenn der zugehörige Prozess stirbt. Einige GDC-Handles z.B.

    meinste GDI-handles? das war mal zur zeit der 16-bit windosen, win98, win-me und so. die nt-abkömmlinge räumen alles sauber wieder weg.
    🙂

    Ne, ich meine eher sowas wie Icon-Handles. Da steht sogar explizit dabei, dass die nicht wieder weggeräumt werden.



  • Tachyon schrieb:

    Ne, ich meine eher sowas wie Icon-Handles. Da steht sogar explizit dabei, dass die nicht wieder weggeräumt werden.

    kann ich mir nicht vorstellen, haste 'nen link?
    🙂



  • +fricky schrieb:

    Tachyon schrieb:

    Ne, ich meine eher sowas wie Icon-Handles. Da steht sogar explizit dabei, dass die nicht wieder weggeräumt werden.

    kann ich mir nicht vorstellen, haste 'nen link?
    🙂

    Jo hast recht. Das war wirklich zur Prä-NT-Ära. Ich habe schon 'ne Weile nichts mehr mit der Win-API gemacht. Auf jeden Fall isses aber neuer als IBM/360.
    Die Funktionen waren LoadIcon, CreateIcon etc.



  • Hallo zusammen!
    Vielen Dank für eure Hilfe!
    Leider stehe ich aber irgendwie immer noch aufm Schlauch.
    Ich bekomme immer noch den "Segmentation fault"-Fehler.

    Hab meine Datei mal ausgemistet und aufs nötigste reduziert:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    
    char **getTitles(int *n){
    	char *pfad = "./data.txt";
    	char **titles = (char**)malloc(20*sizeof(char * ));
    	char *c;
    	FILE *f;
    	int i = 0;
    	f = fopen(pfad, "r");
            if(f==NULL) {
                perror("Error: can't open file.\n");
                }else{
                while(fgets(c, 95, f)!=NULL && i<20) {
    		titles[i] = (char*)malloc(96 * sizeof(char));
                    strncpy(titles[i],c,95);
                    i++;
                }
                fclose(f);
    	    *n = i+1;
    	    return titles;
            }
    }
    
    int main(void){
    	int *cntTitles = 0;
    	char **titles = getTitles(cntTitles);
    	int i;
    
    	for(i=0;i<*cntTitles;i++){
    		printf("%s", titles[i]);
    	}
    
    	for(i=0;i<*cntTitles;i++){
    		free(titles[i]);
    	}
    	free(titles);
    	return EXIT_SUCCESS;
    }
    

    Was ist daran noch falsch?

    Grüsse klopf-klopf



  • Auf was zeigt denn Dein Pointer c ?



  • while(fgets(c, 95, f)!=NULL && i<20) {
    titles[i] = (char*)malloc(96 * sizeof(char));
    strncpy(titles[i],c,95);
    i++;
    }
    

    auf den String der fgets() eingelesen hat. (Oder?)

    Grüsse klopf-klopf



  • klopf-klopf schrieb:

    while(fgets(c, 95, f)!=NULL && i<20) {
    titles[i] = (char*)malloc(96 * sizeof(char));
    strncpy(titles[i],c,95);
    i++;
    }
    

    auf den String der fgets() eingelesen hat. (Oder?)

    Grüsse klopf-klopf

    fgets braucht einen Puffer, in den eingelesen wird. c zeigt aber nicht auf einen Puffer, sondern irgendwo hin.


Anmelden zum Antworten