<?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[static und Destruktur-Aufruf]]></title><description><![CDATA[<p>Hallo!<br />
Ich möchte für mein Programm einen Resourcenpool schreiben (intern std::queue), aber davon soll der Nutzercode nichts merken. Aus gewissen Gründen ist diese queue ein statischer Member einer Template-Klasse.<br />
In dem Pool sind nur leider Resourcen, die ich freigeben müsste, aber erst am Ende des Programms (da, wo statischer Speicher freigegeben wird). Wie kann ich das machen?</p>
<pre><code class="language-cpp">struct resource {
   resource() {
      cout &lt;&lt; &quot;Allocated&quot; &lt;&lt; endl;
   }

   ~resource() {
      cout &lt;&lt; &quot;Deallocated&quot; &lt;&lt; endl;
   }
};

std::deque allocate_resources() { ... } // RVO, daher copy return
void deallocate_resources(std::deque&amp;) { ... }

template &lt;typename T&gt;
struct type {
   static std::queue&lt;resource&gt; resources;
};

std::queue&lt;resource&gt; type::resources(allocate_resources()); // Wird noch vor main() aufgerufen

int main() {
   cout &lt;&lt; &quot;Startup&quot; &lt;&lt; endl;
   type t;
   cout &lt;&lt; &quot;Shutdown&quot; &lt;&lt; endl;
}
</code></pre>
<p>Gewünschte Ausgabe:</p>
<pre><code>Allocated!
Allocated!
Allocated!
...
Startup
Shutdown
Deallocated!
Deallocated!
Deallocated!
...
</code></pre>
<p>Die &quot;Deallocated&quot;-Nachrichten kommen natürlich nie, da ja nirgends deallocate_resources() aufgerufen wird. Wie kann ich das machen? Im Usercode soll später nichts von dem Pool zu sehen sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/280842/static-und-destruktur-aufruf</link><generator>RSS for Node</generator><lastBuildDate>Mon, 24 Aug 2026 00:17:59 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/280842.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 22 Jan 2011 17:42:29 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sat, 22 Jan 2011 17:45:48 GMT]]></title><description><![CDATA[<p>Hallo!<br />
Ich möchte für mein Programm einen Resourcenpool schreiben (intern std::queue), aber davon soll der Nutzercode nichts merken. Aus gewissen Gründen ist diese queue ein statischer Member einer Template-Klasse.<br />
In dem Pool sind nur leider Resourcen, die ich freigeben müsste, aber erst am Ende des Programms (da, wo statischer Speicher freigegeben wird). Wie kann ich das machen?</p>
<pre><code class="language-cpp">struct resource {
   resource() {
      cout &lt;&lt; &quot;Allocated&quot; &lt;&lt; endl;
   }

   ~resource() {
      cout &lt;&lt; &quot;Deallocated&quot; &lt;&lt; endl;
   }
};

std::deque allocate_resources() { ... } // RVO, daher copy return
void deallocate_resources(std::deque&amp;) { ... }

template &lt;typename T&gt;
struct type {
   static std::queue&lt;resource&gt; resources;
};

std::queue&lt;resource&gt; type::resources(allocate_resources()); // Wird noch vor main() aufgerufen

int main() {
   cout &lt;&lt; &quot;Startup&quot; &lt;&lt; endl;
   type t;
   cout &lt;&lt; &quot;Shutdown&quot; &lt;&lt; endl;
}
</code></pre>
<p>Gewünschte Ausgabe:</p>
<pre><code>Allocated!
Allocated!
Allocated!
...
Startup
Shutdown
Deallocated!
Deallocated!
Deallocated!
...
</code></pre>
<p>Die &quot;Deallocated&quot;-Nachrichten kommen natürlich nie, da ja nirgends deallocate_resources() aufgerufen wird. Wie kann ich das machen? Im Usercode soll später nichts von dem Pool zu sehen sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010273</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010273</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sat, 22 Jan 2011 17:45:48 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sat, 22 Jan 2011 18:01:42 GMT]]></title><description><![CDATA[<p>Mach für deine type::resources halt einen Typ der im Konstruktor allocate_resources() und im Destruktor deallocate_resources() aufruft (genau das was dein struct resource da tut, wofür is das eigentlich wenn dus nirgendwo verwendest)!? Du musst dabei nur aufpassen dass die Reihenfolge in der statische Variablen initialisiert werden nicht definiert ist. Wenn du also ein anderes globales/statisches Objekt hast das von diesem Ding abhängt dann hast du ein Problem. Ansonsten funzt das aber wunderbar.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010283</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010283</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sat, 22 Jan 2011 18:01:42 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sat, 22 Jan 2011 18:36:04 GMT]]></title><description><![CDATA[<blockquote>
<p>&gt; Mach für deine type::resources halt einen Typ der im Konstruktor allocate_resources() und im Destruktor deallocate_resources() aufruft</p>
</blockquote>
<p>Dann müsste ich ja std::queue wrappen, und alles wie pop, push, front etc. definieren. Das ist sehr umständlich.<br />
Sollte ich von queue ableiten?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010304</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010304</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sat, 22 Jan 2011 18:36:04 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sat, 22 Jan 2011 18:51:58 GMT]]></title><description><![CDATA[<p>Jodocus schrieb:</p>
<blockquote>
<p>Dann müsste ich ja std::queue wrappen, und alles wie pop, push, front etc. definieren.</p>
</blockquote>
<p>So what!? Und außerdem kannst du dem Typ auch einfach eine Methode geben die ne Referenz auf die queue zurückgibt oder die Variable public machen. Abgesehen davon stellt sich die Frage ob du wirklich das allgemeine Interface einer queue haben willst (was soll das Ding denn genau machen?). Und ansonsten werden natürlich über den Destruktor der queue auch die Objekte in der Queue zerstört, also deren Destruktoren aufgerufen, vielleicht kannst du auch damit was anfangen.</p>
<p>EDIT: Ich seh grad dass du letzteres eh schon in deinem Beispielcode verwendest, das ist mir oben entgangen. Wo genau liegt denn dort das Problem, die Destruktoren sollte da aufgerufen werden, wenn nicht dann ist dein Compiler grob fehlerhaft.</p>
<p>Jodocus schrieb:</p>
<blockquote>
<p>Sollte ich von queue ableiten?</p>
</blockquote>
<p>Auf keinen Fall.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010306</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010306</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sat, 22 Jan 2011 18:51:58 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sat, 22 Jan 2011 18:45:55 GMT]]></title><description><![CDATA[<blockquote>
<p>&gt; Auf keinen Fall.</p>
</blockquote>
<p>Nur, weil der Destruktor von std::queue nicht virtuell ist? Das macht doch nix, die abgeleitete Klasse definiert ja keine neuen Member, sondern nur ein neuer Konstruktor/Destruktor. Polymorph muss der Typ ja nicht sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010309</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010309</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sat, 22 Jan 2011 18:45:55 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sat, 22 Jan 2011 19:26:28 GMT]]></title><description><![CDATA[<p>Die std:: Container sind nicht dazu gedacht dass man davon ableitet. Auch wenn das in deinem konkreten Fall im Moment keine wirklichen Probleme bereitet ist es trotzdem hässlich. Warum nicht einfach ordentlich machen?</p>
<p>Wie gesagt: Was genau repräsentiert diese queue? Brauchst du wirklich das komplette allgemeine Interface (vermutlich nicht)? Wo genau liegt eigentlich das Problem mit deiner Lösung über dieses resource struct? Die Destruktoren müssten nämlich eigentlich aufgerufen werden, wenn nicht dann wäre das ein ziemlich grober Fehler in deinem Compiler. Oder schaut dein echter Code doch grundsätzlich anders aus (dein Beispielcode ist nämlich syntaktisch nicht ganz korrekt)? Sollte nämlich eigentlich funktionieren: <a href="http://codepad.org/AKYb0SKq" rel="nofollow">http://codepad.org/AKYb0SKq</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010312</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010312</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sat, 22 Jan 2011 19:26:28 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sun, 23 Jan 2011 12:22:42 GMT]]></title><description><![CDATA[<p>Ich werde wohl mal noch etwas konkreter, zumal ich jetzt immer mehr Fragen bekomme.</p>
<blockquote>
<p>&gt; Wie gesagt: Was genau repräsentiert diese queue?</p>
</blockquote>
<p>Den Speicher, wo die Resourcen des Pools liegen. Sobald eine Resource angefordert wird, wird sie aus der Queue entfernt und einem RAII-Objekt übergeben. Sobald das zerstört wird, wird das Handle in die Queue zurückgeschrieben.<br />
Diese Queue befindet sich eben im statischen Speicher (als ein Klassenmember einer Template-Instanz). Das heißt also, dass zum Programmbeginn der Pool initialisiert wird (sofern irgendwann im Code das Template instantiiert wird). Nur habe ich jetzt das Problem, dass ich die Resourcen aus der Queue freigeben muss, wenn die Queue selbst zerstört wird:</p>
<pre><code class="language-cpp">// Diese Struktur muss ganz am Anfang und ganz am Ende des Programmes in Aktion treten ---&gt; static-Instanz
struct library_guard {
   library_guard() {
      if(system_api::init_library() == false) {
         // Fehler aufgetreten - was tun? Exceptions sind hier nicht möglich, da nicht von außen fangbar
         // std::abort()? Dann kann der Anwender nicht sehen, was passiert ist. ?
      }
   }

   ~library_guard() {
      if(system_api::free_library() == false) {
         // Problem wie im Konstruktor
      }
    }
};

namespace {
   library_guard guard__; // statisches Objekt, wird es als erstes instantiiert?
}

std::deque create_handles() {
   typedef std::deque&lt;unsigned&gt; handle_deque; // deque deshalb, weil später mehr Handles dazukommen
   handle_deque handles(1024);                // vector eignet sich zum Hinzufügen von Elementen nicht
   for(handle_deque::size_type n = 0; n &lt; handles.size(); ++n)
      if((handles[n] = system_api::allocate(...)) == false) {
         // Fehler aufgetreten - was tun? Exceptions sind hier nicht möglich, da nicht von außen fangbar
         // std::abort()? Dann kann der Anwender nicht sehen, was passiert ist. ?
      }
   return handles; // Wird als R-Value benutzt ---&gt; copy return optimiert durch RVO
}

template &lt;typename T&gt;
struct A {
   static std::queue&lt;unsigned&gt; handles; // Statisch, da von A keine Objektinstanz erstellt werden darf
private:
   A();
};

template &lt;typename T&gt;
std::queue&lt;unsigned&gt; A&lt;T&gt;::handles(create_handles()); // &lt;---- das wird nun vor main() initialisiert, falls im Code ein Template von A&lt;&gt; instantiiert wird
/*
aber static-Instantiierungs-Reihenfolge ist unbekannt; Wie kann library_guard _davor_ instantiiert werden?
*/

int main() {
   ...
}
</code></pre>
<p>Am Ende der Anwendung wird der von der std::queue benutze Heap-Speicher freigegeben. Aber ich muss explizit die Handles freigeben. Wie kann ich das elegant machen, ohne das std::queue-Interface nachzubauen? Und wie handhabe ich die Fehlerbehandlung und die Instantiierungs-Reihenfolge?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010540</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010540</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sun, 23 Jan 2011 12:22:42 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sun, 23 Jan 2011 12:21:39 GMT]]></title><description><![CDATA[<p>ein singleton?<br />
Im Konstruktor die initialisierung oder eine fuktion dafür bereit stellen. Diese dan vor main() aufrufen.<br />
Im Destruktor dan alles wieder frei geben.</p>
<p>Zu: // Fehler aufgetreten - was tun? Exceptions sind hier nicht möglich, da nicht von außen fangbar<br />
Fehler-Flag setzen und dan bei begin von main() abfragen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010545</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010545</guid><dc:creator><![CDATA[BigNeal]]></dc:creator><pubDate>Sun, 23 Jan 2011 12:21:39 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sun, 23 Jan 2011 12:25:09 GMT]]></title><description><![CDATA[<p>Der Clue ist, dass ich library_guard im Usercode gerne verdecken möchte. Da man den immer braucht, könnte die Library sie doch selber aufrufen, weshalb ich ein statisches Objekt vom Guard erzeuge.</p>
<blockquote>
<p>&gt; Im Konstruktor die initialisierung oder eine fuktion dafür bereit stellen. Diese dan vor main() aufrufen.</p>
</blockquote>
<p>Wie rufe ich eine Funktion vor main() auf? Das geht AFAIK nur in Konstruktoren von globalen (statischen) Objekten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010546</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010546</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sun, 23 Jan 2011 12:25:09 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sun, 23 Jan 2011 12:33:23 GMT]]></title><description><![CDATA[<p>Jodocus schrieb:</p>
<blockquote>
<p>Sobald eine Resource angefordert wird, wird sie aus der Queue entfernt und einem RAII-Objekt übergeben. Sobald das zerstört wird, wird das Handle in die Queue zurückgeschrieben.</p>
</blockquote>
<p>Warum auch immer du dafür eine globale Instanz brauchst...Jedenfalls braucht dieses Ding dann nach außen hin wie vermutet wohl nicht das interface einer queue sondern offenbar nur genau zwei (statische) Methoden, eine um eine Ressource anzufordern und eine weitere um sie wieder freizugeben!?</p>
<p>Jodocus schrieb:</p>
<blockquote>
<p>Nur habe ich jetzt das Problem, dass ich die Resourcen aus der Queue freigeben muss, wenn die Queue selbst zerstört wird</p>
</blockquote>
<p>Warum packst du in deine queue anstatt von unsigned int nicht einfach einen Typ der sich über ref counting oder so drum kümmert dass alles freigegeben wird?</p>
<p>Die Reihenfolge in der solche globalen Objekte initialisiert werden ist nur zwischen verschiedenen Übersetzungseinheiten undefiniert. Alle globalen Variablen die <em>in der selben</em> .cpp Datei definiert sind werden in der Reihenfolge initialisiert in der sie definiert sind.</p>
<p>Trotzdem würd ich mir überlegen ob dieses Singleton-ähnliche Design wirklich so eine gute Idee ist. Wenn du mich fragst wäre es wohl besser irgendwo im Programm so einen Ressourcen Pool zu erzeugen und dann allen Objekte die ihn brauchen eine Referenz drauf zu geben. Damit lösen sich praktisch alle Probleme von selbst, auch die Probleme mit den Exceptions und vor allem natürlich die großen <a href="http://www.google.at/search?q=singleton+evil" rel="nofollow">Probleme die durch ein Singleton erst erzeugt werden</a>.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010547</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010547</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sun, 23 Jan 2011 12:33:23 GMT</pubDate></item><item><title><![CDATA[Reply to static und Destruktur-Aufruf on Sun, 23 Jan 2011 13:16:16 GMT]]></title><description><![CDATA[<blockquote>
<p>&gt; Warum auch immer du dafür eine globale Instanz brauchst...</p>
</blockquote>
<p>Für mich ist ein Pool was globales, ein allgemeiner Speicher.</p>
<blockquote>
<p>&gt; Jedenfalls braucht dieses Ding dann nach außen hin wie vermutet wohl nicht das interface einer queue sondern offenbar nur genau zwei (statische) Methoden, eine um eine Ressource anzufordern und eine weitere um sie wieder freizugeben!?</p>
</blockquote>
<p>Nach außen existieren auch nur genau diese 2 statischen Memberfunktionen. Die queue dient - wie gesagt - nur als interner Speicher. Welchen Container ich hier benutzte spielt zunächst auch keine Rolle, er muss eben nur korrekt alles anfordern und freigeben</p>
<blockquote>
<p>&gt; Warum packst du in deine queue anstatt von unsigned int nicht einfach einen Typ der sich über ref counting oder so drum kümmert dass alles freigegeben wird?</p>
</blockquote>
<p>Was bringt mir eine Queue von shared_ptrs? Die Objekte sollen alle am Ende des Programms freigegeben werden (von der Library, nicht vom Usercode).</p>
<blockquote>
<p>&gt; Trotzdem würd ich mir überlegen ob dieses Singleton-ähnliche Design wirklich so eine gute Idee ist.</p>
</blockquote>
<p>Mein Hirn ist quasi schon verknotet, da dieses Problem für mich so kniffelig ist. Ich will eben 2 Sachen gleichzeitig verdecken: den Pool (der soll nämlich auch austauschbar sein, damit am Usercode nichts geändert werden muss), der quasi wie ein künstlicher Heap-Speicher funktionieren soll und die System-Library-Instanz (eine Windows DLL-Instanz), welche für alle Operationen im Zusammenhang mit der Library benutzt wird.<br />
Einfache Lösung wäre eben:</p>
<pre><code class="language-cpp">#include &quot;meine_library.hpp&quot;

int main() {
   load_library();
   {
     resource_pool pool(100); // 100 Elemente im Pool
     resource r1 = pool.get(); // RAII-Objekt r1 bekommt Resource, die aus dem Pool gelöscht wird
   } // r1 wird zerstört, Destruktor kann interne Resource in pool zurückschreiben, Pool wird zerstört --&gt; Resourcen an System freigegeben
   free_library();
}
</code></pre>
<p>Aber ich will:</p>
<pre><code class="language-cpp">#include &quot;meine_library.hpp&quot;

int main() {
   // System-Library automatisch laden/freigeben (vor der main() nur mit static möglich, aber keine Exceptions :(
   // Pool in der Library automatisch erstellen
   resource r1; // Konstruktor benutzt den library-internen Pool und nimmt eine Resource heraus
} // r1 wird zerstört --&gt; Resource wird in internen Pool zurückgeschrieben

// Der interne Pool muss nun irgendwie nach der main() freigegeben werden (mit static möglich, aber leider keine Exceptions :(
</code></pre>
<p>Wie kann ich das nur erreichen? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2010579</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2010579</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sun, 23 Jan 2011 13:16:16 GMT</pubDate></item></channel></rss>