Speicherprobleme bei sehr großen struct arrays



  • heyho
    brauche sehr große 2 bzw. auch 3 dimensionale struct arrays. der code sieht folgendermaßen aus:

    const int n=500, number_machines=3;
     struct jo{
        int process; 
        int capacity;
        int release; 
        int value;   
        int index;
        int einsortiert;
        int batch_process;
        int batch_release;
        int batch_capacity; 
        int machine;   
        int start;   
           } job[1],batch[n+1][n+1],candidate[1],knapsack[1], best[number_machines][n][n];
    

    leider bekomm ich da speicher fehler, so ab n=100. kann ich irgendwie manuell zusätzlichen speicher für das programm beschaffen?

    Vielen Dank!



  • Jürgen123 schrieb:

    leider bekomm ich da speicher fehler, so ab n=100. kann ich irgendwie manuell zusätzlichen speicher für das programm beschaffen?

    Vielen Dank!

    heyho

    du könntest mal versuchen den ganzen speicher nicht in dein programm reinzukompilieren...? also ums einfach zu halten verwende malloc() calloc() oder nutze deine eigene variante und lager das was du nicht so oft brauchst auf ne disk aus...

    lg lolo



  • Du bekommst einen stack overflow, ja? Ist auch kein Wunder. Allein 'best' soll ein Array mit 3*500*500 Elementen sein, bei einer Struktur, die über 40 Bytes groß ist. Das macht dann schon mal so ca. 30 MB! Dein Stack ist deutlich kleiner (z.B. 1 MB). Solche großen Arrays legt man stattdessen auf dem Heap ab. Dazu kannst du Speicher allozieren mit malloc und mit free wieder freigeben.



  • Was für Speicherfehler bekommst du denn?
    Aber wie _matze schon schrieb musst du definitiv einen StackOverflow bekommen.

    Wenn du lokale Variablen deklarierst speicherst du diese statisch auf dem Stack. Und dafür sind deine Variableins ein kleines bisschen zu groß. Du kannst die Stack Größe zwar manipulieren, aber dass sollte man a) sowieso nicht machen und b) ist die Dimension zu weit von der default Grenze entfernt.

    malloc() allokiert speicher auf dem heap. Da kannst du unter Windows 32-Bit 2 GB verbraten. Sollte im Prinzip reichen.



  • FrEEzE2046 schrieb:

    Was für Speicherfehler bekommst du denn?

    ich dachte das geht nicht durch den compiler 😕

    lg lolo



  • Jürgen123 schrieb:

    leider bekomm ich da speicher fehler

    okay okay hab mein fehler schon gefunden 😞 muß mal die posts genauer lesen

    lg lolo



  • 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..



  • Entfern die mehrfachen Dimensionen und reduzier alles auf eine Dimension, dann ist es viel einfacher.

    struct Foo *f = malloc(sizeof(*f) * 50); /* Platz für 50 mal struct Foo */
    


  • // 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.


Anmelden zum Antworten