realloc und dynamisches array



  • hi,

    ich habe eine template-klasse die ein dynamisches array darstellt.

    // MinAlloc ist entweder 1 oder wird im konstruktor auf einen beliebigen wert gesetzt
    // TotalCount gibt die gesamtzahl der reservierten elemente an (anfang = 0)
    // FreeItems gibt die anzahl der noch freien elemente an (anfang = 0)

    //---------------------------------------------------------------------------
    // Funktion Allocate()
    //---------------------------------------------------------------------------
    template <class T> bool TRSDynamicList<T>::Allocate(int Size)
    {
      try
      {
        if (!Size)
          Size = MinAlloc;
    
        TotalCount += Size;
        FreeItems   = Size;
        Items       = (T*) realloc(Items, TotalCount * sizeof(T));
    
        if (!Items)
        {
          Error("TRSDynamicList [Allocate]", "Not enough memory!");
          return false;
        }
    
        return true;
      }
      catch(...)
      {
        Error("TRSDynamicList [Allocate]", "Error while allocating memory!");
        return false;
      }
    }
    

    realloc verhält sich laut hilfe bei einem NULL-Zeiger (sprich wenn noch kein element reserviert wurde) wie malloc und ansonsten wird der speicher-block vergrössert.

    struct test
    {
      int a;
      int b;
    };
    
    // neue liste mit zeigern auf objekte anlegen
    TRSDynamicList <test*> *Liste = new TRSDynamicList <test*>;
    
    // 10.000 elemente erzeugen
    for (int i = 0; i < 10000; i++)
    {
      test *t1 = new test;
      Liste->Add(t1);
    }
    

    folgendes problem:

    wenn ich obigen beispiel-code ausprobiere, reserviert mir das im einzelschritt (d.h. für jedes listenelement wird einmal Allocate() aufgerufen) über 100 megabyte an arbeitsspeicher. wenn ich dagegen von vorn herein sage, dass ich 10000 element benötige, wird nur der speicher reserviert der auch tatsächlich nötig ist.

    wieso? wie kann ich diese fehlreservierung verhindern?



  • evtl am besten, indem du die immer nur 8k große blöcke beschaffst und so.

    aber war es nicht so, daß realloc nur versucht, den speicher zu vergrößern, und wenns nicht klappt, einfach nen neuen speicher besorgt? dann müßest du den alten selber freigeben.



  • der alte speicher wird von realloc automatisch freigegeben.
    realloc versucht einen neuen speicherplatz zu schaffen, wenn das funktioniert, wird der alte speicherbereich da rein kopiert und dann wieder mit delete gelöscht



  • otze schrieb:

    wenn das funktioniert, wird der alte speicherbereich da rein kopiert

    ups, ja.
    man kann in c ja einfach kopieren.



  • ja aber trotzdem wird gigantisch viel speicher reserviert. wenn ich das ganz mit malloc und memmove mache anstatt mit realloc, läuft es auf das gleiche hinaus.

    es funktioniert auch, wenn ich die liste nur vom typ 'test' erstelle (d.h. keine liste von zeigern).



  • Items       = (T*) realloc(Items, TotalCount * sizeof(T));
    

    Das ist ziemlich unclever. Wenn realloc fehl schlägt, wird Items null. Der bisherige Speicher bleibt aber trotzdem reserviert und dein Zeiger darauf ist futsch (seitdenn du hast vorgesorgt und Items wird nur temporär genutzt).

    SundayWork schrieb:

    wenn ich das ganz mit malloc und memmove mache anstatt mit realloc, läuft es auf das gleiche hinaus.

    Speicher wird immer unabhängig voneinander reserviert, dh er überlappt sich nicht. memmove ist aber genau für solche Zwecke gedacht und von daher hier überflüssig. Ein memcpy tut es genauso.

    Liegt dein Problem vielleicht hier:

    TotalCount += Size;
    

    Mit jedem Aufruf von Allocate summiert sich der Speicher auf. Ist das wirklich so beabsichtigt?


Anmelden zum Antworten