# Fragen zu: "Speicherverwaltung", "dynamische Arrays in Klassen"



## busenbach (22. August 2007)

Hallo,
ich habe ein kleines Problem mit „Speicherverwaltung“, vielleicht kann mir ja jemand helfen.


Hintergrund des Problems:
Ich möchte ein Programm schreiben, dass Signale (hier: Impulse) analysiert um deren Werte zu ermitteln wie z.B. Hochpunkt, Tiefpunkt, Pulsdauer, usw. Die Impulsdaten erhalte ich vom Scope in Form einer Textdatei in der deren Punkte enthalten sind.

Problem:
Ich habe es anfangs mit einem Array von [2000] gearbeitet und alles hat wunderbar geklappt dann aber wurde mir gesagt, dass es auch mit mindesten 1mio Datenpunkten funktionieren soll. Ich habe schlichtweg die Arraygröße dementsprechend vergrößert und was passierte wohl: Speicher übergelaufen





Frage 1
######
Mittlerweile habe ich alles im Griff, ich habe immer die Arrays auf Reserve aufgestockt und so klappt alles, aber das erscheint mir nicht ganz als elegante Lösung und außerdem habe ich Angst, dass ich wirklich mal an die Grenzen des Pcs komme deswegen meine erste Frage
----1) Kann ich wirklich beim Rechner den Speicher vollaufen lassen? Ich habe einen Array [4mio] (double) und mehrere mit [50k] (double, int) und es werden noch einige dazukommen. Ich habe keinerlei Erfahrung mit so was und habe auch überhaupt kein Gefühl das einschätzen zu können.

Frage 2
######
Ich arbeite mit einer Klasse und dachte ich kann etwas tricksen indem ich einfach in einer Methode ein Array[50k] erstelle, da es ja beim Schließen wieder gelöscht wird, aber da ist der Speicher ebenfalls vollgelaufen (denke mal der Stack hats nicht verkraftet).
Dann dachte ich an dynamische Speicherverwaltung (new, delete) und da wäre meine nächste Frage
----2)Ich kann im normalen main() mit „new“ und „delete“ Zeiger erstellen und wieder löschen, aber wie kann ich das in einer Klasse realisieren? Ich möchte in „private“ einen Zeiger haben, diesen je nachdem wann ich den brauche initialisieren und damit auch in „verschiedenen“ Methoden damit arbeiten können und dann natürlich auch wieder freigeben, das heißt: ich will den Zeiger nicht in einer Methode initialisieren, wo diese am Ende wieder gelöscht wird, sondern möchte diesen auch im „private-Bereich“ für andere Methoden zugänglich machen und bei Bedarf löschen.


Hoffe ich habe mich verständlich ausgedrückt oder ihr könnt wenigstens erahnen was ich meine  bin da nicht der Hellste in der Thematik
Danke im Voraus
mf


----------



## Drache2 (23. August 2007)

Hi. Ich bin zwar auch nicht der helste, aber ich versuch mal zu helfen.

Zu Frage 1:

Es kommt , soweit ich das sehe, unteranderm auch auf's Betribssystem an. Bei Xp wird das Programm beim Speicherüberlauf beended, Vista dagegen, schafft irgentwie immer neuen peicherplatz indem es andere stellen leert. (habs mit nem Programm was dem Arbeitsspeicher überfüllt(selbsgeschrieben) getestet).
Ansonsten würe ich empfehelen, nur so große Werte wie nötig zu nehmen (weis ja nicht ob du solch große Zahlen benötigst).

Zu Frage 2:

Zeiger erstellst du eigentlich so:

int *Zeiger;

Speicherplatz resevierst du so:

Zeiger=new int;

aber ich denke du meintest das so^^

Es klingt für mich zudem ein bischen verwirrend, aber, mach den Zeiger doch einfach global...

Ich hoffe ich konte helfen


----------



## busenbach (23. August 2007)

1)
Habe hier leider Windows 2000  benutze es selber zum ersten mal

2)
Ich will es schon eine Klasse nutzen, einfach wegen der Organisation. Ich weiss halt nicht wie ich dynamische Zeiger in einer Klasse managen kann, so dass auch andere darauf zugriff haben und meine Daten nach beenden der Methode nicht verloren gehen

trotzdem danke!


----------



## MCoder (23. August 2007)

Hallo,

1.) Den Speicher vollaufen lassen, sollte eigentlich kaum passieren. Ist der physische Speicher voll, wird auf Festplatte ausgelagert. Das wird wirkt sich dann zwar negativ auf die Performance aus, aber ist ein anderes Thema.

2.) Eine Deklaration in der Form "Array[groesse];" reserviert den Speicher immer auf dem Stack und da kommt man natürlich mit hohem Speicherbedarf schnell an die Grenzen. Der Speicher muss also auf dem Heap (etwa mit "new") reserviert werden.

Innnerhalb einer Klasse kannst du als Member einen Zeiger auf eine Variable für den Speicher anlegen und mit entsprechendenMethoden verwalten, z.B.:

```
class CDoubleMem
{
public:
    CDoubleMem()
    {
        m_pData = 0;
    }
    
    ~CDoubleMem()
    {
        if( m_pData )
        {
            delete [] m_pData;
        }
    }
    
    void SetSize(int nSize)
    {
        if( m_pData )
        {
            delete m_pData;
        }
        
        m_pData = new double[nSize];
    }
                            
    // ... Weitere Methoden

private:
    double *m_pData;                    
};
```
Gruß
MCoder


----------



## busenbach (23. August 2007)

MCoder hat gesagt.:


> Hallo,
> 
> 1.) Den Speicher vollaufen lassen, sollte eigentlich kaum passieren. Ist der physische Speicher voll, wird auf Festplatte ausgelagert. Das wird wirkt sich dann zwar negativ auf die Performance aus, aber ist ein anderes Thema.
> 
> ...




ah, genau so auf diese Art und Weise habe ich es mir vorgestellt! habs auch so ähnlich ausprobiert, aber ich hatte immer ein kleines Problem was ich nicht so recht verstehe:

-mit dem Konstrukter initialisiere ich den Wert Standardgemäß mit 0
-mit "SetSize" kann ich die Größe bestimmen
hier mein Problem:
-Ich hatte mit dem Destruktor oft Probleme, weil wenn ich den benutzt habe wurden auch alle meiner anderen Daten in der Klasse gelöscht (ich will ja nur explizit die Zeiger löschen die ich nicht mehr brauche, alle anderen sollen erhalten bleiben). Ich habe das dann so gemacht, indem ich einfach eine Methode "DeleteSize"erstellt habe die dann nur den "delete []"-Befehl für den speziellen Zeiger ausführt.

Löscht der Destruktor dann wirklich auch ALLE anderen Daten mit oder würde er bei deinem Beispiel "nur" das "m_pData" löschen?
-->ich schätze mal ich muss für jedes dynamische Array eine extra DeleteSize-Methode haben

vielen dank nochmal!


----------



## MCoder (23. August 2007)

busenbach hat gesagt.:


> Ich hatte mit dem Destruktor oft Probleme, weil wenn ich den benutzt habe wurden auch alle meiner anderen Daten in der Klasse gelöscht (ich will ja nur explizit die Zeiger löschen die ich nicht mehr brauche, alle anderen sollen erhalten bleiben).


Der Destruktor wird automatisch aufgerufen, wenn das Objekt zerstört wird. Damit sind natürlich auch alle Daten dieser Instanz gelöscht. Auf dem Heap reservierten Speicher muss man immer explizit löschen, weil es sonst Memory Leaks gibt. Der Destruktor ist dafür ein guter Ort, weil mit dem Ende des Objektes dieser Speicher sowieso obsolet wird.

Willst du vor dem Ende des Objektes den Speichern löschen kannst du entweder eine spezielle Delete-Methode implementieren oder die SetSize-Methode aufrufen, weil diese vorher den "alten" Speicher löscht.

Gruß
MCoder


----------



## busenbach (23. August 2007)

MCoder hat gesagt.:


> Der Destruktor wird automatisch aufgerufen, wenn das Objekt zerstört wird. Damit sind natürlich auch alle Daten dieser Instanz gelöscht. Auf dem Heap reservierten Speicher muss man immer explizit löschen, weil es sonst Memory Leaks gibt. Der Destruktor ist dafür ein guter Ort, weil mit dem Ende des Objektes dieser Speicher sowieso obsolet wird.
> 
> Willst du vor dem Ende des Objektes den Speichern löschen kannst du entweder eine spezielle Delete-Methode implementieren oder die SetSize-Methode aufrufen, weil diese vorher den "alten" Speicher löscht.
> 
> ...




ja, ich möchte variabel während dem Programm einzelne bestimmte Zeiger-Arrays erstellen/löschen, also nicht alles auf einmal.
Werde dann bei der "DeleteSize"-Methode bleiben.
danke


----------

