[solved] realloc() - Möglichkeiten des Fehlschlagens



  • Hi Leute,
    bin grad voll vernagelt. Ein Konstrukt, das ich eigentlich oft verwende, stirbt mir aus unerfindlichen Gründen beim realloc() und ich brauche irgendwelche Ansätze, um den Bug einzukreisen.
    Also, prinzipiell will ich eine list/array of structs anlegen, wo ich Zwischenergebnisse zur Endauswertung parke.
    Beim ersten Element klappt alles, läßt sich auch auslesen, aber das erste Draufsatteln geht schief.
    Wie die struct aussieht, ist eher akademischer Natur, sie heißt "minmaxset".
    In der main lege ich Liste, Zähler und einzelnes Element an:

    int main(int argc, char *argv[])
    {
    minmaxset local_minmax;
    minmaxset *minmaxtable = NULL;
    int minmax_elements = 0;
    // ...
    	FindMinMax(axetable, &local_minmax, &elements);
        errors |= AddMinMax(&minmaxtable, &local_minmax, &minmax_elements);
        errors |= AddMinMax(&minmaxtable, &local_minmax, &minmax_elements);
        printf("Minmaxset %d: Complete Axe\n", minmax_elements - 1);
        MinMaxOut(minmaxtable[minmax_elements - 1]);
    

    Das ist jetzt Debug, ich schreibe zweimal das gleiche Element in die Liste. Kommentiere ich das zweite AddMinMax() aus, tut alles wie erwünscht, da kommt alles raus, was FindMinMax() ermittelt hat. Das Böse lauert also in AddMinMax(). Gucken wir rein:

    int AddMinMax(minmaxset **minmaxtable, minmaxset *new_minmaxset, int *minmax_elements)
    {
        if (!(*minmax_elements))
                *minmaxtable = malloc(sizeof(minmaxset));
        else
            *minmaxtable = realloc(*minmaxtable, sizeof(minmaxset) * ((*minmax_elements) + 1));
        (*minmax_elements)++;
        if (!(*minmaxtable))
            return -1;
        else
        {
            minmaxtable[(*minmax_elements) - 1] = new_minmaxset;
            return 0;
        }
    }
    

    Und das Ding kackt mir im zweiten Aufruf beim realloc() immer ab. Ich überseh' doch hoffentlich nur eine Kleinigkeit, weil mich das langsam wahnsinnig macht.
    Ich bitte um einen entspannten Blick drauf, weil ich es momentan einfach nicht sehe, wo der Hase im Pfeffer liegt.

    Mal Danke fürs Hingucken.



  • @Sarkast sagte in realloc() - Möglichkeiten des Fehlschlagens:

    *minmaxtable = realloc(*minmaxtable, sizeof(minmaxset) * ((*minmax_elements) + 1));

    Generell sind schon 2 Dinge doof:

    1. Im main ist die Variable: minmaxset *minmaxtable, während in der Funktion minmaxset **minmaxtable ist. Verwirrt dich sowas nicht?
    2. Es schonmal doof, wenn du direkt den return-Wert von realloc wieder zuweist. Im Fehlerfall verlierst du so das Original. Weise das Ergebnis einer anderen Vriablen zu. reallocated = realloc(...). Dann teste reallocated auf den Nullpointer. Wenn ja, Fehler. Wenn nein, erst DANN überschreibe deinen ursprünglichen Pointer und addiere 1 zu der Anzahl Elemente. Nicht andersrum.

    Ansonsten wäre ein reprodzierbares, vollständiges Beispiel gut. Finde diese Art der Speicherbehandlung aber so mäh, lieber einmal ordentlich in wiederverwertbar machen.



  • Es fällt auf, dass das Keyword struct beim Parameter new_minmaxset fehlt.



  • @john-0 sagte in realloc() - Möglichkeiten des Fehlschlagens:

    Es fällt auf, dass das Keyword struct beim Parameter new_minmaxset fehlt.

    Ich maskier das immer über typedef.

    typedef struct _minmaxset_{
    	double pos_min;
    	double pos_max;
    	int git_pos_min;
    	int git_pos_max;
    	int trc_pos_min;
    	int trc_pos_max;
    	double vel_min;
    	double vel_max;
    	int git_vel_min;
    	int git_vel_max;
    	int trc_vel_min;
    	int trc_vel_max;
    	double acc_min;
    	double acc_max;
    	int git_acc_min;
    	int git_acc_max;
    	int trc_acc_min;
    	int trc_acc_max;
        double m;
        double t;
        int elements;
    } minmaxset;
    

    Deswegen sieht man davon nix.



  • @wob Hi, ich habs jetzt mal zusammengeramscht und vereinfacht. Nur noch ein Intarray. Beim vorherigen Beispiel hab ich ja die Abfragen extra rausgeschmissen, ums zu kürzen. Und ich breche sowieso das Programm ab, wenn ich den Speicher nicht bekomme.

    #include <stdio.h>
    #include <stdlib.h>
    
    int AddInt(int **intarray, int  *new_int, int *array_elements)
    {
        if (!(*array_elements))
        {
                *intarray = malloc(sizeof(int));
    
        }
        else
        {
            *intarray = realloc(*intarray, sizeof(int) * ((*array_elements) + 1));
            printf("reallocated: %d + 1 Elements\n", *array_elements );
        }
    
        (*array_elements)++;
    
        if (!(*intarray))
            return -1;
        else
        {
            // stirbt hier beim 2. Durchlauf
            *intarray[(*array_elements) - 1] = (*new_int) + 1;
            return 0;
        }
    }
    
    int main()
    {
    	int *intarray = NULL;
        int i, j, count, errors = 0;
    
    	count = 0;
    
    	for(i=0; (i<10) && !errors ; i++)
        {
            errors |= AddInt(&intarray, &i, &count );
            printf("i:%d count:%d\n", i, count);
            for(j = 0; (j < count); j++)
                if(!errors)
                printf("array[%d]: %d\n", j, intarray[j]);
        }
        return errors;
    }
    


  • Was ist:

    *intarray[(*array_elements) - 1]

    (Tipp: überlege dir, ob * oder [] stärker binden und ob du nicht deinem Programm ( und ) spendieren willst...)

    (Edit: dein Name der Variablen ist immer noch misleading. Dein intarray ist ein ptr_to_intarray. Dann wär's vielleicht einfacher aufgefallen. Ich hatte oben schon "Verwirrt dich sowas nicht?" gefragt. Denn mich verwirrt sowas.)



  • @wob OK, right to left- Auswertung.
    mit

    (*intarray)[(*array_elements) - 1] = (*new_int) + 1;
    

    tut's. 🙂
    Ich muß nochmal gucken, wo ich noch sowas verbockt haben könnte. Füher habe ich Einzelzuweisungen auf struct- Member verwendet mittels "->", das scheint anders aufgelöst zu werden. Schien mir unnötige Schreiberei, arbeiten auf einer lokalen struct praktikabler und in einem Rutsch als komplette Struct abzulegen. Natürliche Faulheit kommt von Innen. 😅
    So, du meintest, die doppelte Dereferenzierung formal vermeiden zu können? Ich verwende halt gerne kongruente Benennungen, wenn sich die scopes nicht überlappen. Dann weiß ich sowohl außen als auch innen, wovon man codet. Ich weiß nicht, ob's eleganter geht, aber belehr' mich. Gerne.
    Und einen Link, falls zur Hand der ganzen Bindungen wäre nicht nur für mich gut. Ich setze ganz gerne in Klammern, wo ich mir nicht sicher bin, aber eine "Table of Idiotenregeln" hab ich noch nicht gefunden.
    Jedenfalls mal ganz fettes "Danke"! 👍 👏


Anmelden zum Antworten