<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Eigene Speicherverwaltung für Objekte auf dem Heap - Eure Meinung]]></title><description><![CDATA[<p>Hi,</p>
<p>oft muss ich in meinen Programmen Zeiger auf Objekte zurück geben. Ich bin also gezwungen das Objekt auf dem Heap zu erstellen. Jedenfalls wollte ich mich nicht immer um das freigeben per delete kümmern (wurde delete schon aufgerufen bla bla bla). Ich habe mir mal folgendes Konzept überlegt und wollte einfach mal eure Meinung dazu hören:<br />
Ich habe eine Basisklasse CBase. Alle Klassen die meine Speicherverwaltung nutzen, müssen von dieser Klasse abgeleitet werden.<br />
1. Es gibt ein globales, statisches, dynamisches Array dass als Heap-Liste dient... Es speichert jedes Objekt das auf dem Heap liegt.</p>
<pre><code class="language-cpp">static std::set&lt;void *&gt; HeapObjects;
</code></pre>
<p>2. CBase überläd den new operator. Der Zeiger der innerhalb der Operatorfunktion erstellt wird wird in einem dynamischen Array abgelegt.<br />
3. CBase hat eine Funktion SafeDelete() die, falls sie bei einem Stackobjekt aufgerufen wird, nichts tut, bei einem Heap Objekt sich selbst zerstört.<br />
4. CBase ist bei mir in einer DLL. Wird die DLL also freigegeben, so wird für alle Objekte die noch in der Heap-Liste sind SafeDelete() aufgerufen.</p>
<p>So nun erstmal die Klasse:</p>
<pre><code class="language-cpp">class CBase
{
public:
	virtual ~CBase() //Der Destruktor soll überschreibbar sein... jede Klasse kann so ihre eigenen Aufräumarbeiten machen
	{
		this-&gt;Release(); //Aufruf der Speicherfreigabe
	}

	static void *operator new(size_t size)
	{
		void *pMemBlock;

		pMemBlock = malloc(size);
		HeapObjects.insert(pMemBlock); //Hinzufügen des Pointers zur Heap-Liste

		return pMemBlock;
	}

	static void operator delete(void *ptr)
	{
		free(ptr);
	}

	virtual void Release() //Diese Funktion soll als interne Speicherfreigabefunktion dienen...
	{
		//Jede Klasse muss also ihren benutzen Speicher verwalten und hier frei geben (deshalb selbstverständlich virtual)... CBase soll nicht dafür zuständig
		//sein um bei mehrfachen Release() aufrufen, zu prüfen ob der Speicher schon freigegeben wurde
		//Dies soll die Klasse selber tun
	}

	void SafeDelete() //Diese Funktion soll seinen Zeiger aus der Heap-Liste löschen und nur den Klassenzeiger löschen
	{
		if(HeapObjects.find(this) != HeapObjects.end()) //Gelöscht wird nur wenn this in der Heap-Liste ist (also per new erstellt wurde). Objekte auf dem Stack haben also keinen Schaden falls SafeDelete() aufgerufen wird
		{
			this-&gt;Release(); //Erstmal den gesamten Speicher den die Klasse benutzt freigeben
			HeapObjects.erase(this); //Zeiger aus der Liste austragen
			delete this; //Speicher freigeben
		}
	}
};
</code></pre>
<p>Zu 4.</p>
<pre><code class="language-cpp">while(HeapObjects.size())
{
	CBase *pObject = (CBase *)*HeapObjects.begin();

	pObject-&gt;SafeDelete();
	HeapObjects.erase(pObject);
}
</code></pre>
<p>Und mal eine Beispielklasse die CBase nutzt:</p>
<pre><code class="language-cpp">class Sample : public CBase
{
private:
	char *ptr;
	int i;
public:
	Sample(bool b)
	{
		this-&gt;ptr = NULL;
		this-&gt;i = 100;

		if(b) //Das hier ist nur um die Release() Methode richtig zu demonstrieren
		{
			this-&gt;ptr = (char *)malloc(200);
		}
	}

	void hi()
	{
		cout &lt;&lt; &quot;Hi&quot; &lt;&lt; this-&gt;i &lt;&lt; endl;
	}

	void Release()
	{
		if(this-&gt;ptr) //Egal wie oft Release() aufgerufen wird... der Speicher wird so nur einmal freigegeben
		{
			free(this-&gt;ptr);
			this-&gt;ptr = NULL;
		}
	}
};

//...

Sample *p = new Sample(true);
	p-&gt;SafeDelete();
	p-&gt;hi();
</code></pre>
<p>Probleme:<br />
-Das erste tritt schon im Beispiel auf. p-&gt;SafeDelete() löscht das Objekt vom Heap... danach wird p-&gt;hi() aufgerufen, was natürlich scheiße ist.</p>
<p>So, das isses erstmal. Ich weiß da is jetzt null Fehlerüberprüfung drin und natürlich muss für new[] noch das selbe wie für new gelten aber das ganze ist erstmal nur ein Konzept.<br />
Kritiken sind sehr erwünscht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Mfg, Keep Coding <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/topic/291205/eigene-speicherverwaltung-für-objekte-auf-dem-heap-eure-meinung</link><generator>RSS for Node</generator><lastBuildDate>Mon, 17 Aug 2026 19:35:47 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/291205.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 12 Aug 2011 16:06:58 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Eigene Speicherverwaltung für Objekte auf dem Heap - Eure Meinung on Fri, 12 Aug 2011 16:06:58 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>oft muss ich in meinen Programmen Zeiger auf Objekte zurück geben. Ich bin also gezwungen das Objekt auf dem Heap zu erstellen. Jedenfalls wollte ich mich nicht immer um das freigeben per delete kümmern (wurde delete schon aufgerufen bla bla bla). Ich habe mir mal folgendes Konzept überlegt und wollte einfach mal eure Meinung dazu hören:<br />
Ich habe eine Basisklasse CBase. Alle Klassen die meine Speicherverwaltung nutzen, müssen von dieser Klasse abgeleitet werden.<br />
1. Es gibt ein globales, statisches, dynamisches Array dass als Heap-Liste dient... Es speichert jedes Objekt das auf dem Heap liegt.</p>
<pre><code class="language-cpp">static std::set&lt;void *&gt; HeapObjects;
</code></pre>
<p>2. CBase überläd den new operator. Der Zeiger der innerhalb der Operatorfunktion erstellt wird wird in einem dynamischen Array abgelegt.<br />
3. CBase hat eine Funktion SafeDelete() die, falls sie bei einem Stackobjekt aufgerufen wird, nichts tut, bei einem Heap Objekt sich selbst zerstört.<br />
4. CBase ist bei mir in einer DLL. Wird die DLL also freigegeben, so wird für alle Objekte die noch in der Heap-Liste sind SafeDelete() aufgerufen.</p>
<p>So nun erstmal die Klasse:</p>
<pre><code class="language-cpp">class CBase
{
public:
	virtual ~CBase() //Der Destruktor soll überschreibbar sein... jede Klasse kann so ihre eigenen Aufräumarbeiten machen
	{
		this-&gt;Release(); //Aufruf der Speicherfreigabe
	}

	static void *operator new(size_t size)
	{
		void *pMemBlock;

		pMemBlock = malloc(size);
		HeapObjects.insert(pMemBlock); //Hinzufügen des Pointers zur Heap-Liste

		return pMemBlock;
	}

	static void operator delete(void *ptr)
	{
		free(ptr);
	}

	virtual void Release() //Diese Funktion soll als interne Speicherfreigabefunktion dienen...
	{
		//Jede Klasse muss also ihren benutzen Speicher verwalten und hier frei geben (deshalb selbstverständlich virtual)... CBase soll nicht dafür zuständig
		//sein um bei mehrfachen Release() aufrufen, zu prüfen ob der Speicher schon freigegeben wurde
		//Dies soll die Klasse selber tun
	}

	void SafeDelete() //Diese Funktion soll seinen Zeiger aus der Heap-Liste löschen und nur den Klassenzeiger löschen
	{
		if(HeapObjects.find(this) != HeapObjects.end()) //Gelöscht wird nur wenn this in der Heap-Liste ist (also per new erstellt wurde). Objekte auf dem Stack haben also keinen Schaden falls SafeDelete() aufgerufen wird
		{
			this-&gt;Release(); //Erstmal den gesamten Speicher den die Klasse benutzt freigeben
			HeapObjects.erase(this); //Zeiger aus der Liste austragen
			delete this; //Speicher freigeben
		}
	}
};
</code></pre>
<p>Zu 4.</p>
<pre><code class="language-cpp">while(HeapObjects.size())
{
	CBase *pObject = (CBase *)*HeapObjects.begin();

	pObject-&gt;SafeDelete();
	HeapObjects.erase(pObject);
}
</code></pre>
<p>Und mal eine Beispielklasse die CBase nutzt:</p>
<pre><code class="language-cpp">class Sample : public CBase
{
private:
	char *ptr;
	int i;
public:
	Sample(bool b)
	{
		this-&gt;ptr = NULL;
		this-&gt;i = 100;

		if(b) //Das hier ist nur um die Release() Methode richtig zu demonstrieren
		{
			this-&gt;ptr = (char *)malloc(200);
		}
	}

	void hi()
	{
		cout &lt;&lt; &quot;Hi&quot; &lt;&lt; this-&gt;i &lt;&lt; endl;
	}

	void Release()
	{
		if(this-&gt;ptr) //Egal wie oft Release() aufgerufen wird... der Speicher wird so nur einmal freigegeben
		{
			free(this-&gt;ptr);
			this-&gt;ptr = NULL;
		}
	}
};

//...

Sample *p = new Sample(true);
	p-&gt;SafeDelete();
	p-&gt;hi();
</code></pre>
<p>Probleme:<br />
-Das erste tritt schon im Beispiel auf. p-&gt;SafeDelete() löscht das Objekt vom Heap... danach wird p-&gt;hi() aufgerufen, was natürlich scheiße ist.</p>
<p>So, das isses erstmal. Ich weiß da is jetzt null Fehlerüberprüfung drin und natürlich muss für new[] noch das selbe wie für new gelten aber das ganze ist erstmal nur ein Konzept.<br />
Kritiken sind sehr erwünscht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Mfg, Keep Coding <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2105446</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2105446</guid><dc:creator><![CDATA[1700]]></dc:creator><pubDate>Fri, 12 Aug 2011 16:06:58 GMT</pubDate></item><item><title><![CDATA[Reply to Eigene Speicherverwaltung für Objekte auf dem Heap - Eure Meinung on Fri, 12 Aug 2011 16:25:26 GMT]]></title><description><![CDATA[<p>&quot;safe delete&quot; verheisst nie was Gutes <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /></p>
<p>Dein Ansatz erinnert mich an den Nachbau eines Garbage Collectors, wie man es z.B. in antiken GUI-Frameworks gemacht hat. Das &quot;C&quot;-Präfix ist auch <a href="http://www.c-plusplus.net/forum/p2005233#2005233" rel="nofollow">schon länger nicht mehr in Mode</a>. Mit <code>void*</code> kannst du auch nicht mehr typsicher löschen. <code>delete this</code> ist ab und zu ein Anzeichen von schlechtem Design und fehlender Symmetrie (freigeben soll der Besitzer des Speichers – irgendein kapselndes Objekt, aber normalerweise nicht das Objekt selbst).</p>
<p>Das würde ich wirklich nicht machen, damit verwirrst du jeden C++-Programmierer. In modernem C++ benutzt man RAII – ist sehr einfach zu implementieren, aber wahnsinnig effektiv. Warum gibst du nicht einfach Smart-Pointer zurück? Am besten <code>std::unique_ptr</code> , sonst <code>std::auto_ptr</code> oder bei geteiltem Ownership <code>std::shared_ptr</code> .</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2105451</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2105451</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 12 Aug 2011 16:25:26 GMT</pubDate></item><item><title><![CDATA[Reply to Eigene Speicherverwaltung für Objekte auf dem Heap - Eure Meinung on Sat, 13 Aug 2011 13:58:32 GMT]]></title><description><![CDATA[<p>hi nexus,</p>
<p>das &quot;C&quot;-Präfix benutze ich ganz gerne weil ich für per Autovervollständigung nur &quot;C&quot; eingeben muss und dann kommen gleich alle Klassennamen... ich muss also nicht nochmal extra nachgucken wie die Klasse nun genau heißt.<br />
delete wird ja nie für einen void* angewendet. Das delete wird ja immer in SafeDelete() aufgerufen und da ist this ein CBase <em>. Die Zeiger werden halt nur als void</em> abgespeichert aber ich könnte sie genauso gut als CBase * speichern.</p>
<p>Ja das mit dem delete this finde ich auch nicht perfekt. Da muss irgendwie noch ne bessere Lösung her. Smart-Pointer sind für mich keine Option da ihr Destruktor immer delete benutzt. Ich habe z.B. eine Funktion die prüft ob ein bestimmtes Objekt schon vorhanden ist, falls ja ein Zeiger darauf zurück gibt, falls nein ein neues Objekt mit new erstellt. Das Problem ist aber dass mindestens ein Objekt auf dem Stack liegt. Das ist eigentlich auch der Grund warum ich angefangen hab die Klasse zu schreiben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2105696</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2105696</guid><dc:creator><![CDATA[1700]]></dc:creator><pubDate>Sat, 13 Aug 2011 13:58:32 GMT</pubDate></item><item><title><![CDATA[Reply to Eigene Speicherverwaltung für Objekte auf dem Heap - Eure Meinung on Sat, 13 Aug 2011 20:01:33 GMT]]></title><description><![CDATA[<p>1700 schrieb:</p>
<blockquote>
<p>Smart-Pointer sind für mich keine Option da ihr Destruktor immer delete benutzt</p>
</blockquote>
<p>Das ist nicht ganz richtig.</p>
<p><a href="http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/shared_ptr.htm" rel="nofollow">http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/shared_ptr.htm</a> schrieb:</p>
<blockquote>
<p>template&lt;class Y, class D&gt; shared_ptr(Y * p, D d);<br />
template&lt;class Y, class D, class A&gt; shared_ptr(Y * p, D d, A a);</p>
<p>Requirements: p must be convertible to T *. D must be CopyConstructible. The copy constructor and destructor of D must not throw. The expression d(p) must be well-formed, must not invoke undefined behavior, and must not throw exceptions. A must be an Allocator, as described in section 20.1.5 (Allocator requirements) of the C++ Standard.</p>
<p>Effects: Constructs a shared_ptr that owns the pointer p and the deleter d. The second constructor allocates memory using a copy of a.</p>
<p>Postconditions: use_count() == 1 &amp;&amp; get() == p.</p>
<p>Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
<p>Exception safety: If an exception is thrown, d(p) is called.</p>
<p>Notes: When the the time comes to delete the object pointed to by p, the stored copy of d is invoked with the stored copy of p as an argument.</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/2105789</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2105789</guid><dc:creator><![CDATA[ntrnt]]></dc:creator><pubDate>Sat, 13 Aug 2011 20:01:33 GMT</pubDate></item><item><title><![CDATA[Reply to Eigene Speicherverwaltung für Objekte auf dem Heap - Eure Meinung on Sun, 14 Aug 2011 19:48:19 GMT]]></title><description><![CDATA[<p>gut das gilt für die boost smart pointer aber nich für die in der standard library</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2106114</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2106114</guid><dc:creator><![CDATA[1700]]></dc:creator><pubDate>Sun, 14 Aug 2011 19:48:19 GMT</pubDate></item><item><title><![CDATA[Reply to Eigene Speicherverwaltung für Objekte auf dem Heap - Eure Meinung on Sun, 14 Aug 2011 20:35:08 GMT]]></title><description><![CDATA[<p>1700 schrieb:</p>
<blockquote>
<p>Die Zeiger werden halt nur als void* abgespeichert aber ich könnte sie genauso gut als CBase * speichern.</p>
</blockquote>
<p>Warum tust du es dann nicht? Casten musst du so oder so, mit <code>CBase*</code> wäre wenigstens so viel Code wie möglich typsicher.</p>
<p>1700 schrieb:</p>
<blockquote>
<p>gut das gilt für die boost smart pointer aber nich für die in der standard library</p>
</blockquote>
<p><code>std::shared_ptr</code> und <code>std::unique_ptr</code> sind in aktuellen Standardbibliotheks-Implementierungen vorhanden, bei beiden kannst du benutzerdefinierte Deleter angeben. Ausserdem gibts <code>std::tr1::shared_ptr</code> schon seit 6 Jahren.</p>
<p>Glaub mir, was du versuchst, ist reinstes Gefrickel. Du hast nach wie vor alle Nachteile der manuellen Speicherverwaltung, wenn du <code>SafeDelete()</code> explizit aufrufen musst. Zum Beispiel hast du keine Exceptionsicherheit, der Code wird komplexer, mehrere Rückgabewerte sind eine Fehlerquelle, der Aufrufer muss sich um Dinge kümmern, die nicht in seiner Verantwortung liegen, und so weiter...</p>
<p>Alles Probleme, die man in sauberem C++ nicht hat. Schau dir einfach mal das RAII-Idiom an.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2106127</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2106127</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sun, 14 Aug 2011 20:35:08 GMT</pubDate></item></channel></rss>