Dynamisches fgets in C

Joe1903

Mitglied
"Wäre"? Bei welcher Bedingung?

Wie meinst du? Das war/ist nur ein Platzhalter für einen Handler, der den Fall behandelt, dass nicht die erwartete Anzahl Bytes gelesen wurde. Im Code davor wurde mittels ftell() gefragt, wieviele Bytes denn in der Datei sind und die Antwort wurde in einer Variable gespeichert. Wenn jetzt maximal diese Grösse gelesen wird und fread() sagt, dass nicht die gesamte Menge gelesen wurde (ggf. weil die Datei in der Zwischenzeit verändert / gelöscht wurde oder das Laufwerk in tausend Splitter zerbarst), haben wir ein Problem.

Im Übrigen:
Hast du dir überlegt, was genau passiert, wenn ein Fehler wie "NO_MEMORY" auftaucht und der Pointer zum Speicher NULL ist, aber du das Programm nicht abbrichst? (Hast du nicht, dein Programm ist ein klassisches Schönwetterprogramm: Wenn alles gut geht (immer genug Speicher da ist), dann sollte es laufen. Wenn nicht, sagst du in deinem Code "¯\_(ツ)_/¯" und drehst der Katastrophe den Rücken)

Gruss
cwriter
Ok danke für den Hinweis.Ich schreib morgen den Code um und poste es hier.Wäre dankbar,wenn du es dir anschauen könntest.
 

Joe1903

Mitglied
"Wäre"? Bei welcher Bedingung?

Wie meinst du? Das war/ist nur ein Platzhalter für einen Handler, der den Fall behandelt, dass nicht die erwartete Anzahl Bytes gelesen wurde. Im Code davor wurde mittels ftell() gefragt, wieviele Bytes denn in der Datei sind und die Antwort wurde in einer Variable gespeichert. Wenn jetzt maximal diese Grösse gelesen wird und fread() sagt, dass nicht die gesamte Menge gelesen wurde (ggf. weil die Datei in der Zwischenzeit verändert / gelöscht wurde oder das Laufwerk in tausend Splitter zerbarst), haben wir ein Problem.

Im Übrigen:
Hast du dir überlegt, was genau passiert, wenn ein Fehler wie "NO_MEMORY" auftaucht und der Pointer zum Speicher NULL ist, aber du das Programm nicht abbrichst? (Hast du nicht, dein Programm ist ein klassisches Schönwetterprogramm: Wenn alles gut geht (immer genug Speicher da ist), dann sollte es laufen. Wenn nicht, sagst du in deinem Code "¯\_(ツ)_/¯" und drehst der Katastrophe den Rücken)

Gruss
cwriter
Kannst du mal nur einem Beispiel zeigen,wie du das machen würdest?
Im Übrigen finde ich nicht,dass es ein Schönwetterprogramm ist,denn sobald eine Funktion als Status etwas anderes als SUCCESS zurückgibt,macht es zwar weiter,aber macht im Grunde "nichts" mehr im Main und gibt den Fehler aus.
 

Joe1903

Mitglied
Und kannst du mal ob schauen ob das korrekt ist?

C++:
int ReadInputToTree(
        WORD **DestTree,
        size_t *Treecount,
        FILE *Input)
{
        int Status = SUCCESS;
        char *Buf = NULL;
        size_t bufsize = 0;
        char *Word = NULL;
        char *bufbase = NULL;
        char *tmp = NULL;


        if (Input != stdin)
        {
                size_t tmp = ftell(Input);
                fseek(Input, 0, SEEK_END);
                bufsize = ftell(Input);
                fseek(Input, tmp, SEEK_SET);


                Buf = (char*)malloc(bufsize);
                if (Buf == NULL)
                {
                        Status = NO_MEMORY_FOR_WORDNODE;
                           goto end;
                }


                if (fread(Buf, sizeof(char), bufsize, Input) != bufsize)
                {
                        printf("The promised amount was not read.\n");
                           exit(1);
                }
        }
        else
        {
                bufsize = 256;
                Buf = calloc(bufsize, sizeof(char));
                if (Buf == NULL)
                {
                        Status = NO_MEMORY_FOR_WORDNODE;
                        goto end;
                }
                bufbase = Buf;
                while (fgets(Buf, (int)(bufsize - (Buf - bufbase)), Input) != NULL)
                {
                        Buf += (int)(bufsize - (Buf - bufbase)) -1;
                        if (bufbase[bufsize - 2] != 0)
                        {
                                tmp = (char*)realloc(bufbase, bufsize * 2);
                                if (tmp == NULL)
                                {
                                        Status = NO_MEMORY_FOR_WORDNODE;
                                        goto end;
                                }
                                Buf = tmp + (Buf - bufbase);
                                bufbase = tmp;
                                bufsize *= 2;
                                bufbase[bufsize - 2] = 0;
                        }
                        Buf = bufbase + strlen(bufbase);
                }
                Buf = bufbase;
        }


        Word = strtok(Buf, NONALPHA);
        while (Status == SUCCESS && Word != NULL)
        {
                Status = AddToTree(DestTree, Treecount, Word);
                if (Status == SUCCESS)
                {
                        Word = strtok(NULL, NONALPHA);
                }
        }
        goto end;

end:
        free(Buf);
        free(bufbase);
        return (Status);
}
 

cwriter

Erfahrenes Mitglied
Im Übrigen finde ich nicht,dass es ein Schönwetterprogramm ist,denn sobald eine Funktion als Status etwas anderes als SUCCESS zurückgibt,macht es zwar weiter,aber macht im Grunde "nichts" mehr im Main und gibt den Fehler aus.
Hm.
Es wurde auf den NULL-Pointer zugegriffen. D.h. das Programm ist abgestürzt. Mit den neuen gotos geht es, ist aber nicht schön (und schlechter für den Computer auszuführen, Stichwort pipeline).
Mal abgesehen davon ist auch Status als Variable überflüssig, denn es ist kein Status (den die Funktion selbst kennen muss), sondern ein Rückgabewert. Aber ist ist dann schon näher an der Maschine.

Das Problem: Dein "Nichts" ist UB. Und das ist schlecht.
Kannst du mal nur einem Beispiel zeigen,wie du das machen würdest?
Nein, da ich nicht weiss, was du meinst.

Gruss
cwriter

/EDIT: Zu deinem neuen Code: Beim Überfliegen habe ich nichts gefunden. Aber das muss nichts heissen.