JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=d0cb4e0bc7bccb6d34be91e261f10f66Medaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Memory Management in Computerspielen
Gehe zu Seite 1, 2  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
David
Super JLI'ler


Alter: 33
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 25.07.2006, 13:27    Titel: Memory Management in Computerspielen Antworten mit Zitat

Memory Management in Computerspielen

1.0 Einleitung
Bei Programmen wird man immer wieder auf das Problem stoßen das die Nutzung des Heaps der des Stacks vorzuziehen ist. Sei es ein schnellerer Programmablauf oder die begrenzte Größe des Stacks.
Der Nachteil der hierbei aber immer ensteht ist, das der Programmierer selbst für die Verwaltung des reservierten Speichers verantwortlich ist. Dies kann bei kleinen Programmen nicht groß ins Gewicht fallen, bei größeren Projekten wird einem aber auffallen das man den Überblick, über den reservierten Speicher, recht schnell verliert. Es besteht die Gefahr das Speicherlecks entstehen, was gerade bei Ressourcenhungrigen Programmen wie Computerspielen ein großes Problem darstellt.
Um diesem Problem vorzubeugen gibt es verschiedene Techniken die es dem Programmierer erleichtern den Speicher zu Verwalten. Smartpointer z.B. bieten eine automatische Freigabe von Speicher. Um aber mit 100 prozentiger Genauigkeit sagen zu können das wirklich jeder, noch so kleine, Speicherbereich freigegeben wurde verwendet man einen Memory Manager.
Der Memory Manager macht nicht anderes als zu protokollieren wann und von wem Speicher reserviert wurde. Am Ende des Programms ist es dann möglich genaue Informationen über den, noch nicht freigegebenen Speicher zu bekommen.
Memory Manager können sehr einfach, aber auch sehr komplex aufgebaut sein. In diesem Beispiel werde ich ein recht einfaches Modell vorzeigen. Es ist aber auch möglich die Funktionsweise der MMU (Memory Management Unit) nachzubilden (Paging etc...) was natürlich sehr viel Komfort bringen würde, aber nicht unbedingt notwendig ist.

2.0 Aufbau des Memory Managers
Der Memory Manager soll grundsätzlich drei Funktionen bieten. Speicher reservieren, Speicher Freigeben und Ausgabe der nicht freigegebenen Chunks.
Es ist sinnvoll ein globales Objekt des Managers zu erzeugen. Hierbei wäre die Verwendung eines Singleton Pattern denkbar.

CPP:
class MemoryMgr : public TSingleton< MemoryMgr >
{
private:
        typedef struct ChunkInfo_t
        {
                const char *file;
                int line;
                size_t size;
                struct ChunkInfo_t *next;
                struct ChunkInfo_t *prev;
        } ChunkInfo_s;

        ChunkInfo_t *chunkInfo;

public:
        MemoryMgr();
        ~MemoryMgr();

        void *Alloc( size_t size, int line, const char *file );
        void Free( void *p, int line, const char *file );
        void DumpMemChunks() const;
};

Listing 1: Deklaration des Memory Manages

Die Struktur ChunkInfo_t beinhaltet alle Informationen die wir benötigen. Außerdem bietet sie die Möglichkeit andere Chunk Informationen zu linken. Dies ist notwendig da wir eine Liste erzeugen wollen um später bequem durch die Chunks navigieren zu können.

2.1 Speicher reservieren
Die Funktion Alloc bietet die Möglichkeit Speicher zu reservieren und gibt einen Zeiger auf die entsprechende Speicherstelle zurück. Außerdem hinterlegt sie diverse Informationen zur reservation, u.A. aus welcher Datei der Speicher reserviert wurde und in welcher Zeile dies geschehen ist.

CPP:
void *MemoryMgr::Alloc( size_t size, int line, const char *file )
{
        int size_needed = sizeof( ChunkInfo_t ) + size;
        void *memory = malloc( size_needed );

        if ( !memory )
        {
                printf( "WARNING: Cannot allocate %d Byte\n", size_needed );
        }
       
        ChunkInfo_t *info = ( ChunkInfo_t *)memory;

        info->file = file;
        info->line = line;
        info->size = size;


        info->next = 0;
        info->prev = 0;

        if ( !chunkInfo )
        {
                chunkInfo = info;
        }
        else
        {
                info->next = chunkInfo;
                chunkInfo->prev = info;
                chunkInfo = info;
        }

        return ( void *)( ( ( ChunkInfo_t *)memory )+1 );
}

Listing 2: Die Methode Alloc

Der Informationsblock wird einfach an den Beginn des reservierten Speicherblocks geschrieben. Als Rückgabewert muss dann die entsprechende Anzahl von Bytes zu der Speicheradresse addiert werden, da die Informationen von „Außen“ ja uninteressant sind.
Es ist allerdings darauf zu achten das eine Freigabe, des zurückgegebenen Zeigers, mittels free() ein undefiniertes Verhalten auslösen würde, da der Zeigern nicht an den beginn des reservierten Speicherbereichs zeigt sondern irgendwo in den selben hinein.
Daher ist es unbedingt notwendig den Speicher mit der entsprechenden Funktion des Memory Managers freigeben zu lassen, da dieses Problem dort berücksichtigt wird.

2.2 Freigaben von Speicher
Die Freigabe verläuft recht unspektakulär. Das interessanteste was passiert ist das entfernen des Chunks aus der verlinkten Liste.

CPP:
void MemoryMgr::Free( void *p, int line, const char *file )
{
        if ( !p )
        {       
                return;
        }

        ChunkInfo_t *info = ( ( ChunkInfo_t *)p )-1;

        if ( info->next )
        {
                info->next->prev = info->prev;
        }

        if ( info->prev )
        {
                info->prev->next = info->next;
        }

        else
        {
                chunkInfo = info->next;
        }

        free( info );
}

Listing 3: Die Methode Free

Zu beachten ist, das der Pointer um die entsprechende Anzahl Bytes dekrementiert werden muss, sodass er wieder auf den Beginn des reservierten Speicherblocks zeigt. Also, recht trivial das ganze!

2.3 Ausgeben der Informationen
Die letzte Methode ist auch nicht komplizierter als die beiden anderen. Es wird einfach die Liste der Chunks durchlaufen und die Informationen an irgendein Outputdevice gesendet. Ich verwende hier die C Funktion printf um beide Sprachen nicht allzu heftig zu vermischen! Wink

CPP:
void MemoryMgr::DumpMemChunks() const
{
        ChunkInfo_t *p = chunkInfo;
        int totalSize = 0;
        int numChunks = 0;

        for ( ; p; p = p->next, ++numChunks )
        {
                totalSize += p->size;

                if ( ( p->size >> 10 ) != 0 )
                {
                        printf( "%8d KB from: %s (line: %d)\n", ( p->size >> 10 ), p->file, p->line );
                }
                else
                {
                        printf( "%8d Byte from: %s (line: %d)\n", p->size, p->file, p->line );
                }
        }

        printf( "%8d bytes allocated totally\n", totalSize );
        printf( "%8d chunks allocated\n", numChunks );
}

Listing 4: Die Methode DumMemChunks


2.4 Überschreiben der Methoden new und delete

Manche werden in ihrem Programm doch lieber auf die Möglichkeiten der Speicherreservierung von C++ zurückgreifen, statt die Funktionen des Memory Managers zu verwenden.
In dem Fall bietet C++ die Möglichkeit die Art der Speicherreservierung selbst zu bestimmen, nämlich durch überschreiben der Methoden operator new, operator new[], operator delete und operator delete[].

In diesen Methoden muss dann ganz einfach die entsprechende Methode des Memory Managers aufgerufen werden.

CPP:
inline void *operator new( size_t size, int line, const char *file ) {
        return MemoryMgr::GetInstance().Alloc( size, line, file );
}

inline void *operator new[]( size_t size, int line, const char *file ) {
        return MemoryMgr::GetInstance().Alloc( size, line, file );
}

inline void operator delete( void *p, int line, const char *file ) {
        MemoryMgr::GetInstance().Free( p, line, file );
}

inline void operator delete[]( void *p, int line, const char *file ) {
        MemoryMgr::GetInstance().Free( p, line, file );
}

inline void *operator new( size_t size ) {
        return MemoryMgr::GetInstance().Alloc( size, 0, "" );
}

inline void *operator new[]( size_t size ) {
        return MemoryMgr::GetInstance().Alloc( size, 0, "" );
}

inline void operator delete( void *p ) {
        MemoryMgr::GetInstance().Free( p, 0, "" );
}

inline void operator delete[]( void *p ) {
        MemoryMgr::GetInstance().Free( p, 0, "" );
}

Listing 5: Überschreiben der Methoden zur Speicherreservierung

Wie zu sehen ist gibt es für alle vier Methoden jeweils zwei Versionen. Zum einen die Standardversion zum anderen eine mit zusätzlichen Parametern, nämlich Zeile und Datei. Beide sind notwendig um eine korrekte Speicherbereitstellung zu gewährleisten.
Als letzten Schritt ersetzt man das Schlüsselwort new durch eine eigene Definition. Hierbei sei es einmal erlaubt #define zu verwenden.

CPP:
#undef new
#define new new( __LINE__, __FILE__ )

Listing 6: Definition von new

Alle Aufrufe von new werden nun durch den entsprechenden Aufruf ersetzt der die Zeilennummer und die Dateibezeichnung als Parameter an die geeignete Funktion weiter gibt. Das verwenden des Managers wird damit denkbar einfach, es sind nämlich keine Änderungen im Quellcode notwendig.
Als Beispiel etwas Quellcode:

CPP:
#include <iostream>
#include "MemoryMgr.h"

class foo
{
private:
        int x, y;

public:
        foo( int x, int y )
        : x( x ), y( y )
        {}

        void dump() const
        {
                std::cout << x << " " << y << std::endl;
        }       

        void setx( int x )
        {
                this->x = x;
        }

        void sety( int y )
        {
                this->y = y;
        }
};


int main( void )
{
        int *x = new int;
        *x = 10;
        std::cout << *x << std::endl;

        foo *bar = new foo( 10, 20 );
        bar->dump();
        bar->setx( 50 );
        bar->dump();

        int *xyz = new int[ 5 ];

        for ( int i = 0; i < 5; ++i )
        {
                xyz[ i ] = i*10;
                printf( "%d\n", xyz[ i ] );
        }

        MemoryMgr::GetInstance().DumpMemChunks();

        delete x;
        delete bar;     
        delete [] xyz;
        return 0;
}

Listing 7: Ein kleines Anwendungsbeispiel

Die Ausgabe des Beispiels sieht folgend aus:

Zitat:

10
10 20
50 20
0
10
20
30
40
20 Byte from: test.cpp (line: 42)
8 Byte from: test.cpp (line: 37)
4 Byte from: test.cpp (line: 33)
32 bytes allocated totally
3 chunks allocated


Nach dem Aufrufen von delete würde die Ausgabe der Chunkliste folgendes bringen:

Zitat:

0 bytes allocated totally
0 chunks allocated



3.0 Schlusswort

Der hier vorgestellte Manager ist wirklich sehr simpel aufgebaut. Es gibt noch viele weitere Ideen welche man hinzufügen könnte, sei es die Unterstützung von Paging oder das unterscheiden von Datenblockgrößen.
Das Prinzip vom Memory Management sollte aber trotzdem klar werden. Ich hoffe desweiteren das einige Nutzen aus dem vorgestelltem Prinzip ziehen können und ihr Programm eventuell Leakfrei bekommen! Wink

Als PDF.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Chriss
Senior JLI'ler



Anmeldedatum: 18.08.2004
Beiträge: 267

Medaillen: Keine

BeitragVerfasst am: 26.07.2006, 06:52    Titel: Antworten mit Zitat

Schick schick aber eine kleinigkeit habe ich zu bemängeln.

Du hast das Template TSingleton nicht beschrieben oder gezeigt. Ich glaube zwar das die meisten das auch selber hinbekommen aber für Anfänger wäre es nicht schlecht wenn sie das Template sehen würden.

Grüße
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
David
Super JLI'ler


Alter: 33
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 26.07.2006, 06:59    Titel: Antworten mit Zitat

Siehe hierzu das Tutorial "Singletons" in der Sektions "Tutorials"! Wink

grüße
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Chriss
Senior JLI'ler



Anmeldedatum: 18.08.2004
Beiträge: 267

Medaillen: Keine

BeitragVerfasst am: 26.07.2006, 08:27    Titel: Antworten mit Zitat

Tutorials: Singleton
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
GreveN
JLI Master


Alter: 31
Anmeldedatum: 08.01.2004
Beiträge: 901
Wohnort: Sachsen - Dresden
Medaillen: Keine

BeitragVerfasst am: 26.07.2006, 12:18    Titel: Antworten mit Zitat

Ich finde diesen C/C++-Mix sehr unschön. Außerdem würde ich es gutheißen, das Memory-Management irgendwie exceptionsicher zu gestalten, wenigstens in dem Destruktor des Managers die restlichen Chunks automatisch freigeben, wenn bis zum Programmende noch nicht durch den User geschehen. Schön wäre natürlich auch, wenn der Speicher, welcher in einem Block reserviert wurde, am Ende des Blockes automatisch freigegeben würde. Stichwort RAII. Was natürlich irgendwie auch wieder auf Smartpointer hinausläuft.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Yahoo Messenger MSN Messenger
David
Super JLI'ler


Alter: 33
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 26.07.2006, 12:30    Titel: Antworten mit Zitat

Hi!

Es liegt im Endeffekt bei dem jeweiligen Entwickler ob der das so gestalten möchte wie du vorschlägst. Ich halte es nicht immer für sinnvoll den Speicher im Destruktor freizugeben, möglicherweiße will ein anderes Objekt diesen Speicher zu einem späteren Zeitpunkt freigeben und schon krachts.

Zum Fehlerhandling, das habe ich ganz bewußt rausgelassen, da ich nur die Basis eines Memory Managers präsentieren wollte, jegliche Erweiterungen sind dem Programmierer überlassen und da Exceptionhandling nicht unbedingt fest mit diesem Thema verknüpft ist habe ich auf eine Implementation mit demselben verzichtet.

Die Idee mit der Speicherfreigabe am ende eines Scopes ist zwar auf den ersten Blick ganz nett, aber sie ist NICHT Aufgabe des Memory Managers. Speicher welcher auf dem Stack liegt hat das Problem nicht und Speicher auf dem Heap muss u.U. über den Scope hinaus gültig bleiben, wenn z.B. andere Objekte auf den Speicher referenziert sind.
Desweiteren kann der Memory Manager nicht testen ob das Programm einen entsprechenden Scope verlässt.
Daher ist diese Idee für einen Memory Manager nicht verwertbar. Wie du schon sagtest gibt es dafür Smartpointer in verschiedenen Variationen.

Nun zum letzten Punkt, der C/C++ Mix. Ich mag das im Grund auch nicht. Ich bin sogar der Meinung C und C++ sollten möglichst überall getrennt sein. ABER: Es macht keinen Sinn Aufrufe wie new/delete in dem Memory Manager zu verwenden. Ansonsten verwende ich printf im Quellcode, welches ja leicht zu ersetzen ist. Die C-Casts kann man auch gern in C++ Casts konvertieren. Hier ging es mir aber eher um das Aussehen des Quellcodes... C++ Casts sind einfach hässlich und würden den Code sehr unleserlich machen.

grüße
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
GreveN
JLI Master


Alter: 31
Anmeldedatum: 08.01.2004
Beiträge: 901
Wohnort: Sachsen - Dresden
Medaillen: Keine

BeitragVerfasst am: 26.07.2006, 13:53    Titel: Antworten mit Zitat

David hat Folgendes geschrieben:
Zum Fehlerhandling, das habe ich ganz bewußt rausgelassen, da ich nur die Basis eines Memory Managers präsentieren wollte, jegliche Erweiterungen sind dem Programmierer überlassen und da Exceptionhandling nicht unbedingt fest mit diesem Thema verknüpft ist habe ich auf eine Implementation mit demselben verzichtet.

Jopp, das stimmt schon, aber ich meinte nicht direkt ein integriertes Exceptionhandling, aber es ist eben sehr unelegant, wenn in einer Funktion Speicher reserviert wird, eine Exception auftritt, die Ausführung abrupt abgebrochen und der reservierte Speicher nie freigeben wird. Deshalb kapselt man Funktionalität, welche auf manuelles Initialisieren und Freigeben von Ressourcen angewiesen ist, getreu dem Grundsatz "Resource Acquisition is Initialization", gerne in eigene Typen, da man so über den Destruktor, welcher beim Verlassen eines Scopes auf jeden Fall aufgerufen wird, sicherstellen kann, dass die reservierten Ressourcen auch wieder freigegeben werden. Übrigens auch sehr schön in Zusammenhang mit diesen hässlichen BeginScene/EndScene-, Lock/Unlock-Blöcken, da Surfaces z.B. unter gegebenen Umständen sonst nie entriegelt werden, was zu Problemen führt - vorausgesetzt man betreibt auch ein anständiges Exceptionhandling. Der Manager könnte sich ja selbst darum kümmern, das spätestens bei Programmende die letzten Chunks automatisch freigegeben werden.

David hat Folgendes geschrieben:
Die Idee mit der Speicherfreigabe am ende eines Scopes ist zwar auf den ersten Blick ganz nett, aber sie ist NICHT Aufgabe des Memory Managers. Speicher welcher auf dem Stack liegt hat das Problem nicht und Speicher auf dem Heap muss u.U. über den Scope hinaus gültig bleiben, wenn z.B. andere Objekte auf den Speicher referenziert sind.
Desweiteren kann der Memory Manager nicht testen ob das Programm einen entsprechenden Scope verlässt.
Daher ist diese Idee für einen Memory Manager nicht verwertbar. Wie du schon sagtest gibt es dafür Smartpointer in verschiedenen Variationen.

Naja, technisch umsetzbar wäre das sicher - z.B. über eine temporäre Instanz einer Hilfsklasse auf dem Stack, welche beim Verlassen des Scopes zerstört wird - aber du hast natürlich recht, dass das nicht Aufgabe eines Memory-Managers ist. ;) Die Frage ob es allzu sinnvoll ist, Speicher zu allokieren und quer durch das Programm darauf zuzugreifen, bleibt natürlich - aber das ist eher eine Frage der Endanwendung, mir persönlich fällt da eigentlich nur der Fall einer Klasse ein, deren Methoden auf einen dynamischen, internen Speicherbereich zugreifen, allerdings sollte sich die Klasse dann auch selber (im Konstruktur/Destruktur) um die Reservierung und Freigabe kümmern.

David hat Folgendes geschrieben:
Nun zum letzten Punkt, der C/C++ Mix. Ich mag das im Grund auch nicht. Ich bin sogar der Meinung C und C++ sollten möglichst überall getrennt sein. ABER: Es macht keinen Sinn Aufrufe wie new/delete in dem Memory Manager zu verwenden. Ansonsten verwende ich printf im Quellcode, welches ja leicht zu ersetzen ist. Die C-Casts kann man auch gern in C++ Casts konvertieren. Hier ging es mir aber eher um das Aussehen des Quellcodes... C++ Casts sind einfach hässlich und würden den Code sehr unleserlich machen.

Ja, war auch eher auf die C-like Deklaration der Chunk-Struktur und der Hardcore-Listen-Implementierung bezogen... ;)


Ich wollte eigentlich nicht direkt kritisieren, eher Denkanregungen bieten, was man bei Bedarf noch anders regeln kann, bzw. wo unter Umständen bei unsachgemäßer Handhabung Fehler auftreten können... ;)
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Yahoo Messenger MSN Messenger
David
Super JLI'ler


Alter: 33
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 26.07.2006, 14:02    Titel: Antworten mit Zitat

Gut, dann seh ich das mal als Ergänzung zu meinem Basismaterial! Smile
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Hazel
JLI MVP
JLI MVP


Alter: 33
Anmeldedatum: 19.07.2002
Beiträge: 1761

Medaillen: Keine

BeitragVerfasst am: 27.07.2006, 16:56    Titel: Antworten mit Zitat

Der Memory Manager sollte noch buchführen, welcher Speicher noch nicht wieder freigegeben wurde und dies eventuell bei Beendigung des Programms automatisch tun und zusätzlich eine Warnung wegen Memory Leaks ausgeben.

Ansonsten ganz netter Artikel, nur ein bisschen dünn erklärt für Leute die nicht viel von dem Thema verstehen... sehr minimalistisch.
_________________
*click* Dabuu!?
Twitter: http://twitter.com/Ollie_R
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
LordHoto
JLI'ler


Alter: 28
Anmeldedatum: 27.03.2003
Beiträge: 137
Wohnort: Gelnhausen
Medaillen: Keine

BeitragVerfasst am: 28.07.2006, 06:26    Titel: Antworten mit Zitat

GreveN hat Folgendes geschrieben:

Ja, war auch eher auf die C-like Deklaration der Chunk-Struktur


was ist denn daran so C like? der typedef? naja das sieht man auch genug in C++ Programmen.... sonst sehen struct definitionen in C eher so aus:
Code:

struct foo { /* something here */ };
struct foo myFoo;

Wobei es mit dem typedef doch angehnehmer ist Wink
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Jonathan_Klein
Living Legend


Alter: 30
Anmeldedatum: 17.02.2003
Beiträge: 3430
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 07.08.2006, 08:24    Titel: Antworten mit Zitat

GreveN hat Folgendes geschrieben:
Außerdem würde ich es gutheißen, das Memory-Management irgendwie exceptionsicher zu gestalten, wenigstens in dem Destruktor des Managers die restlichen Chunks automatisch freigeben, wenn bis zum Programmende noch nicht durch den User geschehen.


Nun, es könnte ja sein, das man ebenfalls eine andere Singleton Klasse hat, weclhe Speicher reserviert und im Konstruktor wieder freigibt.
Da stellt sich jetzt natürlich die Frage, was zuerst aufgerufen wird, wenn der SpeicherManager erste beendet wird, kann das andrer Objekt ncihts mehr mit dem Speichermachen, und ihn freigeben würde evtl. auch Probleme machen. Kann man die Reihenfolge der Destrukturaufrufe verändern? Natürlich könnte jede Singleton Klasse eine ShutDown Methode haben, aber wenn man die dann benutzen würde, würde ja das utomatisch Freigebn im Desturktor sinnfrei sein, obwohl es doch so ne schöne Lösung ist.
Daher sehe ich es als Problematisch an den Speicher automatisch wieder freizugeben. Außerdem resultiert aus meiner Annahm das der Manager Leaks meldet, obwohl diese von einem andern Code noch freigegeben wird.
_________________
http://www.C3-Soft.de
http://www.nikodemus.net
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
GreveN
JLI Master


Alter: 31
Anmeldedatum: 08.01.2004
Beiträge: 901
Wohnort: Sachsen - Dresden
Medaillen: Keine

BeitragVerfasst am: 07.08.2006, 10:53    Titel: Antworten mit Zitat

Das ist so 'ne Sache an den Singletons, ein ziemlich blöder Nebeneffekt, mit dem ich auch öfters zu kämpfen habe.

Normalerweise hat immer die Funktion/Struktur, die Speicher reserviert, ihn auch wieder freizugeben, nun kann man sich streiten, ob die Funktionen/Strukturen, die Speicher _über_ den Manager anfordern, ihn auch wieder _über_ den Manager freizugeben haben, oder, da der Manager ja generell den Speicher reserviert und verwaltet, es demzufolge auch seine Aufgabe ist, dafür zusorgen, dass der Speicher komplett wieder freigegeben wird.

Das Problem an 'init'/'release'-Methoden ist immer, dass sie eben nicht zwangsläufig exceptionsicher sind. Soll diese Methode vor dem Ende eines Blockes aufgerufen werden, das Programm steigt vorher aber durch eine Exception aus, wird diese Methode eben nie aufgerufen. In diesem Fall könnte man das natürlich kompensieren, indem man den Speicher manuell im Exceptionhandler freigibt - was mir unter gegebenen Umständen bald noch als beste (Not-)Lösung erscheint.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Yahoo Messenger MSN Messenger
Jonathan_Klein
Living Legend


Alter: 30
Anmeldedatum: 17.02.2003
Beiträge: 3430
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 07.08.2006, 12:08    Titel: Antworten mit Zitat

Nohc ne Frage: Was passiert, wenn eine Singleton Klasse Speicher freigibt, aber der MemoryManager vorher beendet wurde?
Könnte doch theoretisch passieren, oder?
_________________
http://www.C3-Soft.de
http://www.nikodemus.net
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
David
Super JLI'ler


Alter: 33
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 07.08.2006, 13:09    Titel: Antworten mit Zitat

Könnte passieren, und was wirklich passiert wirst du nicht festmachen können.
Der Memory Manager sollte eben nicht vor Programmende beendet werden! Smile

grüße
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Jonathan_Klein
Living Legend


Alter: 30
Anmeldedatum: 17.02.2003
Beiträge: 3430
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 07.08.2006, 13:24    Titel: Antworten mit Zitat

Er wird aber beim programmende beendet. Singleotns werden erst destruiert, wenn das Programm beendet wird. Hat man allerdings 2 Singletons, ja, welche(r/s) wird dann zuerst beendet? Mir wäre keine Methode bekannt, wie man das festlegen könnte, ich schätze mal das ist mehr oder minder undefiniert. Wenn jetzt ein Singleton nach dem anderen beendet wird (gleichzeitig geht ja net) und der memmoryManager wird zuerst beendet, und dann ein andere(r/s) welche(r/s) im Destruktur den MemoryManager aufruft, was ist dann?

Achja, heißt es der die oder das Singleton?
_________________
http://www.C3-Soft.de
http://www.nikodemus.net
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials Alle Zeiten sind GMT
Gehe zu Seite 1, 2  Weiter
Seite 1 von 2

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum