Speicherprobleme bei sehr großen struct arrays



  • // alte Variante:
    struct jo batch[501][501];	// aufm Stack
    
    // neue Version:
    struct jo** batch = malloc(sizeof(struct jo*) /* 4 o. 8 */ * 501);		// reserviere Speicher für die ganzen Pointer
    for( i = 0; i < 501; i++ )
    	batch[i] = malloc(sizeof(struct jo) * 501);							// reserviere Speicher für 501 structs pro Pointer
    


  • Jürgen123 schrieb:

    Danke schonmal!
    hab ich mir schon fast gedacht mit dem malloc, nur hapert es an der praktischen umsetzung:)
    haette ich jetzt z.b. jo batch; anstelle von jo batch[n][n]
    dann waere es ja wenn ich mich nicht irre einfach:

    batch = (struct jo *) malloc(sizeof(struct jo));
    free(batch);
    

    aber vielleicht kann mir jemand sagen wie das für das array aussieht..

    1. Es wäre jo *batch (man beachte das Sternchen!), denn du willst einen Speicherbereich erzeugen, auf den du mit einem Zeiger zugreifen kannst.

    2. sizeof(struct jo) musst du mit der Anzahl der Elemente deines Wunsch-Arrays multiplizieren. Wenn du also ein 3*500*500-Array haben willst, dann musst du auch sizeof(struct jo)*3*500*500 Bytes allozieren.

    3. In C sollst du die Rückgabe von malloc nicht casten! Also lass den "(struct jo *)"-Cast weg.



  • also ich hab jetzt:
    [cpp]
    const int n=500, number_machines=3;
    struct jo{
    int process;
    int capacity;
    int release;
    };
    jo *batch[n][n] = malloc(n*n*sizeof(struct jo));

    allerdings kommt da einmal subscripted value is neither array nor pointer
    und "jo" undeclared first use in this function

    ?? 🙂



  • oh sorry, hatte die antwort von freeze total übersehn, das funktioniert so wunderbar:)
    Danke an alle!!!



  • Jürgen123 schrieb:

    oh sorry, hatte die antwort von freeze total übersehn, das funktioniert so wunderbar:)
    Danke an alle!!!

    Vergiss nicht am Ende für jeden Aufruf von malloc() auch einmal free() aufzurufen.



  • Hey Freeze, vielleicht kannst du mir nochmal helfen:)

    habe wohl das prinzip noch nich so hundertprozentig verstanden..

    2dimensionale variante

    batch[501][300]
    struct jo** batch = malloc(sizeof(struct jo*) *501 * 300);        // reserviere Speicher für die ganzen Pointer
    for( i = 0; i < 501; i++ ){
           batch[i] = malloc(sizeof(struct jo)*300);
    }
    

    so wenn ich jetzt aber 3 dimensional bin läuft das schon nichmehr:)

    clone[3][501][300]
    struct jo*** clone=malloc(sizeof(struct jo*)*3*501*300);
    for( i = 0; i < 3; i++ ){
         clone[i] = malloc(sizeof(struct jo)*501*300);
    }
    for( i = 0; i < 3; i++ ){
    for(j=0;j<501;j++){ clone[i][j] = malloc(sizeof(struct jo)*300);
    }}
    

    ich frag mich auch ob der speicher so richtig wieder freigegeben wird:

    free(batch);
    for(i=0;i<n;i++)
        free(batch[i]);
        }}
    

    Vielen Dank schon mal wieder im Voraus!



  • Jürgen123 schrieb:

    ich frag mich auch ob der speicher so richtig wieder freigegeben wird:

    free(batch);
    for(i=0;i<n;i++)
        free(batch[i]);
        }}
    

    Du gibst den Speicher für batch frei und greifst anschließend auf genau diesen Speicher zu. Kannst jetzt mal selbst überlegen ob das so richtig ist.



  • Jürgen123 schrieb:

    habe wohl das prinzip noch nich so hundertprozentig verstanden..

    2dimensionale variante
    ...

    Das ganze mit so vielen Zeigern zu machen ist teuer, weil es immer was kostet, einem Zeiger nachzulaufen. Ich würde gleich ein Array nehmen und es beim Zugriff in einen Array-Typ casten, würde mit einem Schlag die ganzen Zeiger entfernen.

    Beispiel mit int's:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        // genug Platz für eine 2x2-Matrix
        int *p = malloc(sizeof(int) * 2 * 2);
    
        p[0] = 0;
        p[1] = 1;
        p[2] = 2;
        p[3] = 3;
    
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                printf("p[%d][%d] -> %d\n", i, j, ((int (*) [2])p)[i][j]);
    
        free(p);
        return 0;
    }
    

    🙂



  • das heisst mit free(batch); lösche ich alle elemente auf einmal, sehr gut:)



  • Jürgen123 schrieb:

    das heisst mit free(batch); lösche ich alle elemente auf einmal, sehr gut:)

    Nein.

    Mit free(batch) gibst du das dynamische Array selbst frei. Nicht die Elemente im Array.

    Aber du gibst das dynamische Array frei, greifst aber direkt danach auf dieses Array zu -> Böse. Ganz böse.



  • ohje das is auch alles sch*****
    da faellt mir nämlich auch auf dass ich das ganze ja so dann garnich im header allokieren kann. die strukturen sollen aber global in mehreren funktionen bekannt sein:(



  • Jürgen123 schrieb:

    ohje das is auch alles sch*****
    da faellt mir nämlich auch auf dass ich das ganze ja so dann garnich im header allokieren kann. die strukturen sollen aber global in mehreren funktionen bekannt sein:(

    Richtig: Programm vernünftig designen.

    Quick & Dirty: Globale Variable nutzen (Deklarationen mit Schlüsselwort extern, Definition in einer Source Datei) mit init-Funktion zum allokieren des Speichers.



  • Darf man fragen, was du überhaupt machen willst. Gibt es wirklich einen Sinn für deine 3 dimensionalen arrays oder machst du das nur so aus Spaß?

    Denn irgendwie ist schon beim Eröffnungspost ein ziemlich krasser Designmakel zu erkennen.



  • Janjan schrieb:

    Richtig: Programm vernünftig designen.

    Gute Idee. Aber ist es denn vernünftiges Design, 450900 unnötige Zeiger zu haben, die nur Probleme machen, und über 450900 mal malloc() und free() aufzurufen?

    Jürgen123 schrieb:

    ohje das is auch alles sch*****

    Warum nicht einfach ein grosses Array von Strukturen nehmen? Wenn dich die mehrdimensionalen Arrays verwirren, kannst du ja die 1d-Indizes auch selbst berechnen.
    🙂



  • mngbd schrieb:

    Janjan schrieb:

    Richtig: Programm vernünftig designen.

    Gute Idee. Aber ist es denn vernünftiges Design, 450900 unnötige Zeiger zu haben, die nur Probleme machen, und über 450900 mal malloc() und free() aufzurufen?

    Nein. Habe ich auch nie behauptet.



  • mngbd schrieb:

    Janjan schrieb:

    Richtig: Programm vernünftig designen.

    Gute Idee. Aber ist es denn vernünftiges Design, 450900 unnötige Zeiger zu haben, die nur Probleme machen, und über 450900 mal malloc() und free() aufzurufen?

    Stimmt gar nicht. Die innerste Dimension ist ja ein zusammenhängender Bereich von Strukturen und nicht von Zeigern. Die Zahl ist 1503.
    🙂



  • hm also das programm mit ein paar kommentaren kann man hier anschaun: http://docs.google.com/View?id=dgvm7qcx_0qbg2x8gg

    ist mir klar dass das alles nicht gut programmiert ist, es muss auch nich total effizient sein nur wäre gut wenn es laufen würde und mir n ergebnis ausspuckt. (gut die rechenzeit dürfte gerne etwas geringer:) )
    es wäre natürlich besser gewesen die felder der structs dynamisch je nach bedarf zu erstellen, das übersteigt aber meine kenntnisse und wie gesagt, solang der computer bei der berechnung nicht abstürzt ises ok:)



  • Da sind aber ein paar Syntaxfehler drin. Kompiliert doch so gar nicht. Wenn die Größe pro Array nur 5 ist (wegen n = 5), dann ist das auch nicht zu groß für den Stack.

    Bei 750.000 sieht's da schon anders aus. Ganz nebenbei: Die Einrückung ist der Horror.



  • super ne:) da merkt man einfach dass da n pro am werke war.
    jetzt läufts...



  • Danke an alle für die tips,
    falls mal jemand das gleiche problem hat, hier ne lösung die funktioniert:

    #ifndef HEADER_H
    #define HEADER_H
    
    #define N=10;
    typedef struct {
     int lala;
     int blabla;
    } my_type_t;
    
    my_type_t *** best;
    my_type_t ** batch;
    
    #endif // HEADER_H
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "header.h"
    
    void init_2d(my_type_t *** var_2d, const int size_x, const int size_y) {
    	int i;
    
    	*var_2d = (my_type_t **) malloc(size_x * sizeof(my_type_t *));
    	for (i = 0; i < size_x; i++) {
    		(*var_2d)[i] = (my_type_t *) malloc(size_y * sizeof(my_type_t));
    	}
    }
    
    /*
     * Initialize dynamic 3-Dimensional Array of Type "my_type_t"
     */
    void init_3d(my_type_t **** var_3d, const int size_x, const int size_y, const int size_z) {
    	int i;
    
    	*var_3d = (my_type_t ***) malloc(size_x * sizeof(my_type_t **));
    
    	for (i = 0; i < size_x; i++) {
    		init_2d(&(*var_3d)[i], size_y, size_z);
    	}
    }
    
    int main(void){
    int i,j;
    init_2d(&batch, N, N);
    init_3d(&best, N, N, N);
    // mach was damit:)
    
    for (i = 0; i < N; i++) {
    		free(batch[i]);
    	}
    	free(batch);
    	for (i = 0; i < N; i++) {
    		for (j = 0; j < N; j++) {
    			free(best[i][j]);
    		}
    		free(best[i]);
    	}
    	free(best);
    return 0;
    }
    

Anmelden zum Antworten