Speicher freigeben für "Dreifach Pointer"



  • Hallo,

    ich hab VS 6.0 mit win 2000.
    Das ist mein Code:

    TCHAR ***Zeile;
    
    Zeile[x] = (TCHAR**) malloc(sizeof(TCHAR**));
    Zeile[x][y] = (TCHAR*) malloc(sizeof(TCHAR)*255);
    fread(Zeile[x][y], sizeof (TCHAR) *255, 1, Binaerdatei);
    Zeile = (TCHAR***) malloc(sizeof(TCHAR***));
    

    1 Feld ist 255 Zeichen lang, die schleifen außenrum hab ich mal weggelassen.

    Meine erste Frage wäre: wie geb ich hier diesen Speicher wieder frei ???
    klar mit free, aber wie:
    free(Zeile); //Fehlermeldug "Damage Error" beim ausführen
    free(Zeile[x]); //debug assertion failed
    free(Zeile[x][y]); // kein Fehler

    Allerdings knallts mit der unteren Variante trotzdem, sobald die der Code ein zweites Mal ausgeführt wird.

    Andere Frage: kann man das generell besser machen, weil in c++ sollte ja speicher mit new reserviert werden und nicht mit malloc ???

    danke voraus für die Hilfe.

    PS: ja ich brauch ein ***Zeile da in der Binärdatei eine Struktur vorhanden ist, die ich kenne und die auch so auslesen möchte. Struktur sieht so aus:
    1 Datensatz (erster Pointer) besteht aus mehreren Feldern(2. Pointer) und dieser aus mehreren Zeichen(3. Pointer)



  • Michael123 schrieb:

    Das ist mein Code:

    TCHAR ***Zeile;
    
    Zeile[x] = (TCHAR**) malloc(sizeof(TCHAR**));
    Zeile[x][y] = (TCHAR*) malloc(sizeof(TCHAR)*255);
    fread(Zeile[x][y], sizeof (TCHAR) *255, 1, Binaerdatei);
    Zeile = (TCHAR***) malloc(sizeof(TCHAR***));
    

    Hier ist schon die Reihenfolge falsch. Die Zuweisung an Zeile muss als erstes erfolgen. Vorher hantierst du mit einem uninitialiserten Zeiger herum.

    Die free-Aufrufe müssen in umgekehrter Reihenfolge der malloc-Aufrufe ausgeführt werden, also zuerst die "inneren" Arrays.

    Ein "Damage"-Fehler weist darauf hin, dass du vorher irgendwo über die Arraygrenzen hinaus geschrieben hast.



  • du hast recht die zuweisung ist falsch rum aber ist hier nur ein copy paste fehler im Forum (leider)

    ok mit dem free hab ich es auch schon von innen nach außen wieder probiert aber dort bekomme ich dann genau die fehlermeldungen die ich schon mit // geschrieben hab...
    danke für deine schnelle antwort.



  • Zeile = (TCHAR***) malloc(sizeof(TCHAR***));

    du reservierst hier dynamischen Speicher für 1 TCHAR***, tust dann aber indizieren als hättest du ein Feld angelegt?
    Ach ja und new wäre wirklich besser:

    Zeile = new **TCHAR;
    

    wenn du ein Feld willst dann

    Zeile = new **TCHAR[x];
    


  • du reservierst hier dynamischen Speicher für 1 TCHAR***, tust dann aber indizieren als hättest du ein Feld angelegt?

    Ja dort sollte ja der Pointer dann stehen auf das Feld [x];

    oder hab ich da jetzt ein Denkfehler drin ??? falls ja werde ich gerne korrigiert...

    allgemein gesagt ich hätte gerne eine Tabelle im speicher von einer Breite X und einer Tiefe von y. in die Zellen sollen dann 255 TCHARS rein vom fread.

    mit:

    Zeile = new **TCHAR[x]
    

    hab ich doch nur mehrere Zeilen untereinander oder bin ich jetzt schon total durcheinander ???



  • struct myTCHAR
    {
       TCHAR tcFeld[255];
    };
    
    myTCHAR **feld = new myTCHAR*[x];
    
    //Feld mit Spalten füllen ...
    myTCHAR *yFeld = new myTCHAR[y];
    feld[0] = yFeld;
    ...
    
    //Zugriff
    feld[0][2] = ...
    

    sowas in der Art? Man kann auch irgendwie direkt mit new ein 2-dim. Feld anlegen, weis jetzt aber leider nicht wie^^

    ach ja hatte oben noch einen Fehler die Sterne müssen nach dem TCHAR stehen( = new TCHAR**[x];)



  • ja genial genau so was in der art suche ich, nur gibt mir halt mein fread kein tchar zurück sondern ein Pointer, deshalb bin ich ja auch beim 3 fach pointer gelandet.
    hast du da vielleicht noch ne idee wie ich das ergebnis vom fread reinkrieg also so:

    int x,y;
    struct myTCHAR
    {
       TCHAR tcFeld[255];
    };
    
    myTCHAR **feld = new myTCHAR*[x];
    
    //Feld mit Spalten füllen ...
    myTCHAR *yFeld = new myTCHAR[y];
    
    for (x=0; x<AnzahlTreffer; x++)
    {
        feld[x] = yFeld;
        for (y=0; y<AnzahlFelder; y++)
        {
            //hier liegt der Hase noch im pfeffer
            fread(feld[x][y], sizeof (TCHAR) *255, 1, Binaerdatei);
        }
    }
    

    danke für deine Hilfe



  • feld[x][y]
    

    Das sorgt dafür das die Zeiger automatisch mit dereferenziert werden, also hast du im Endeffekt ein myTCHAR-Element. Und dieses enthält doch das TCHAR-Feld. Der Name des Feldes ist dabei die Adresse des ersten Elementes, also musst du nur noch das machen:

    fread(feld[x][y].tcFeld, sizeof(myTCHAR), 1, Binaerdatei);
    

    das sizeof(myTCHAR) klappt aber nur, wenn die Struktur wirklich nur das Feld enthält. Falls mehr dazu kommt, musst du mit sizeof die Größe des Feldes tcFeld bestimmen. Das ist aber auf jeden Fall besser als hart im Code die Konstante 255 zu lassen. Was wäre wenn du z.B: auf einmal doch 355 Zeichen brauchst ... .

    ach ja weil du wegen der Freigabe gefragt hattest:
    Du musst zuerst die Spalten freigeben, also deine "yFeld's" und dann das Hauptfeld

    for(int i = 0;i < x;i++)
      delete []feld[i];
    
    delete []Feld;
    

    edit ach ja und denk dran mit

    myTCHAR *yFeld = new myTCHAR[y];
    

    erzeugst du nur EINE Spalte

    wenn du x Spalten der Länge y brauchst, musst das also wieder in eine for-schleife packen

    for(int i = 0;i < x;i++)
      feld[i] = new myTCHAR[y];
    


  • also es läuft jetzt zumindest mal ... allerdings stimmt was mit den pointern noch nicht.
    wenn ich mir dann feld[0][0] ausgeben lasse, bekomme ich immer den letzten Datensatz den fread gelesen hat. Kann es sein dass immer die gleiche Stelle im Speicher überschreibe ???



  • poste mal den (relevanten) Code bitte wie du ihn jetzt hast



  • struct myTCHAR
    {
    	TCHAR tcFeld[255];
    };
    
    int x, y;
    myTCHAR **feld = new myTCHAR*[x];
    myTCHAR *yFeld = new myTCHAR[y];
    
    for (x = 0; x<piAnzahlTreffer; x++)
    {
        feld[x] = yFeld; 
        fseek(Binaerdatei, plErgebnisPointer *sizeof(TCHAR) * 255 * 7,SEEK_SET);
    
        for (int y = 0; y<piAnzahlStrukturfelder; y++)
    	{
    	feld[x]	= new myTCHAR[x];
    	fread(feld[x][y].tcFeld, sizeof (TCHAR) *255, 1, Binaerdatei);
    	}
    }
    

    also in der inneren scheife passt noch alles wenn ich es ausgebe und nach dem verlassen der beiden schleifen gibt feld[0][0] nicht das erste feld vom ersten datensatz aus sondern eben den letzten ... egal welches feld es steht überall der letzte drin ....



  • feld[x]    = new myTCHAR[x];
    

    Also die Spalten haben doch die Anzahl y und nicht x

    Außerdem tust du in JEDEM Durchlauf ein neues Feld erstelle, du brauchst doch aber für x Zeilen die Spalten, also muss das anlegen in der ersten for-Schleife stattfinden und nicht in der zweiten.

    Hab deinen Code mal abgeändert. Ich hoffe das funzt jetzt so und das ich keine Fehler reingemacht habe. Am besten du testest das dann auch mal mit dem Debugger.

    Wie man den Speicher wieder freigibt, habe ich schon gepostet, schaue mal 1,2 Posts vorher.

    struct myTCHAR
    {
        TCHAR tcFeld[255];
    };
    
    int x, y;
    
    //Zeiger auf ein Feld von Zeigern dynamisch anlegen
    myTCHAR **feld = new myTCHAR*[x];
    
    for (x = 0;x < piAnzahlTreffer;x++)
    {
        //ein konkretes myTCHAR-Feld der Länge y anlegen und die Adresse des Feldes
        //in feld an der richtigen Stelle speichern
        feld[x] = new myTHCAR[y]
    
        //Dateizeiger setzen
        fseek(Binaerdatei, plErgebnisPointer *sizeof(TCHAR) * 255 * 7,SEEK_SET);
    
        //das vorher erstellte konkrete  Feld an der Stelle x mit Werten füllen
        for (y = 0;y < piAnzahlStrukturfelder;y++)
        {
            fread(feld[x][y].tcFeld, sizeof (TCHAR) * 255,1,Binaerdatei);
        }
    }
    


  • Mehrfach Arrays sind fast immer eine schlechte Idee. Nicht nur wegen der umstaendlichen Allocierung und Freigabe des Heaps, sondern auch wegen des Zugriffes. Ein Zugriff

    sObject = aMultiArray [3] [5] [10];

    ist fuer den Compiler eine ziemliche Totur und auch langsam. Es ist besser ein eindimensionales Array zu allocieren und eine kleine Funktion fuer den Zugriff zu schreiben, die die Position im Array berechnet.

    Wenn man es schnell machen will, kann die Objecte noch per Zeiger gegeneinander auf Ebenen, Spalten und Zeilen verketten.



  • das ist ja jetzt auch kein "Mehrfach-Array", sondern 2 eindimensionale Felder, wo
    das erste Verweise auf andere eindimensionale Felder hat.

    Aber ich denke ein zweidimensionales Array kann man dem Compiler schon zumuten 🙂



  • Ok danke,

    nun noch mal eine verstädnisfrage, wieso ...
    myTCHAR **feld = new myTCHAR*[x ... nehme ich hier x];

    Das Problem ist, sehr langsam und der speicher explodiert förmlich für 2-3 Sekunden auf 300 MB da ich die Anzahl der Treffer kenne, wäre es nicht besser statt x die Anzahl der Treffer zu nehmen ???

    myTCHAR **feld = new myTCHAR*[piAnzahlTreffer];

    Das gleiche gilt auch für die Anzahl der Strukturfelder ???

    Und dann noch eine Frage zur Freigabe des Speichers, ich gebe jetzt immer den Speicher frei, im Task Manager steigt aber der Speicherverbrauch stetig an, mit jedem Klick auf den Button (welche dann die obige Funktion ausführt). Müsste ich eigentlich nicht im Task Manager sehen dass bei jedem Delete der Speicher abnimmt ???

    Vielen Dank für deine bisherige Hilfe, funktioniert einwandfrei



  • myTCHAR **feld = new myTCHAR*[piAnzahlTreffer];
    

    Du hast natürlich recht^^ Sorry, in dem Bsp-Code habe ich einfach irgendwelche Variablen genommen um keine Konstanten zu benutzen, und da ich das im letzte Post einfach reinkopiert hatte ... .Da muss selbstverständlich die Anzahl stehen, welche du ermittelt hast. 🙂

    Dasselbe gilt natürlich auch für die Strukturfelder.

    Die Freigabe muss dementsprechend auch an deine Variablennamen angepasst werden.

    for(int i = 0;i < piAnzahlTreffer;i++)
      delete [](feld[i]);
    
    delete []Feld;
    

    Wenn du x und y genommen hast, ohne sie vorherzu initialisieren, steht da irgendwas drinnen. Daher kommt dann wohl auch der zu hohe Speicherbedarf.


Anmelden zum Antworten