<?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[Globale Variablen in statischen Bibliotheken]]></title><description><![CDATA[<p>Guten Abend,</p>
<p>ich schreibe an einer Bibliothek, die, wenn sie mit einem Programm gelinkt wird, vor bzw. nach dem Aufruf von main() Code ausführen können muss (Initialisierer/Finalisierer).</p>
<p>Dazu habe ich mich eines Tricks bedient, der die Konstruktoren von globalen Objekten ausnutzt:</p>
<pre><code>class Initializer
{
	Initializer() { puts(&quot;initialisiert!&quot;); }
} initializer;
</code></pre>
<p>Unter Linux funktioniert das bis jetzt gut, meine Bibliothek wird dynamisch gebunden und die Initialisierer initialisieren.<br />
Unter Windows siehts anders aus: Klassen per DLL importieren ist ein Graus, und da es eh keine Paketverwaltung o.ä. gibt, ist es die beste Methode, das statisch zu linken.</p>
<p>Jetzt ist es nur leider so, dass das Objekt irgendwie nicht erstellt wird, wenn es sich in der statischen Bibliothek befindet. Wenn ich stattdessen die Objektdateien direkt mit dem Programm linke, funktioniert alles problemlos.</p>
<p>Ich verwende MinGW (und darauf bin ich angewiesen, um Cross-kompilieren zu können). Beim Erstellen der Bibliothek wird anscheinend eine Symboltabelle generiert, die das Initialisierer-Objekt nicht enthält (Spekulation).</p>
<p>Kann man den Linker dazu bringen, die .o-Dateien einzeln mit dem Programm zu binden anstatt die Tabellen zu verwenden, oder gibt es vielleicht eine ganz andere Lösung für das Problem?</p>
<p>Danke.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/282837/globale-variablen-in-statischen-bibliotheken</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Jul 2026 09:30:50 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/282837.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 27 Feb 2011 18:52:56 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Sun, 27 Feb 2011 18:52:56 GMT]]></title><description><![CDATA[<p>Guten Abend,</p>
<p>ich schreibe an einer Bibliothek, die, wenn sie mit einem Programm gelinkt wird, vor bzw. nach dem Aufruf von main() Code ausführen können muss (Initialisierer/Finalisierer).</p>
<p>Dazu habe ich mich eines Tricks bedient, der die Konstruktoren von globalen Objekten ausnutzt:</p>
<pre><code>class Initializer
{
	Initializer() { puts(&quot;initialisiert!&quot;); }
} initializer;
</code></pre>
<p>Unter Linux funktioniert das bis jetzt gut, meine Bibliothek wird dynamisch gebunden und die Initialisierer initialisieren.<br />
Unter Windows siehts anders aus: Klassen per DLL importieren ist ein Graus, und da es eh keine Paketverwaltung o.ä. gibt, ist es die beste Methode, das statisch zu linken.</p>
<p>Jetzt ist es nur leider so, dass das Objekt irgendwie nicht erstellt wird, wenn es sich in der statischen Bibliothek befindet. Wenn ich stattdessen die Objektdateien direkt mit dem Programm linke, funktioniert alles problemlos.</p>
<p>Ich verwende MinGW (und darauf bin ich angewiesen, um Cross-kompilieren zu können). Beim Erstellen der Bibliothek wird anscheinend eine Symboltabelle generiert, die das Initialisierer-Objekt nicht enthält (Spekulation).</p>
<p>Kann man den Linker dazu bringen, die .o-Dateien einzeln mit dem Programm zu binden anstatt die Tabellen zu verwenden, oder gibt es vielleicht eine ganz andere Lösung für das Problem?</p>
<p>Danke.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027375</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027375</guid><dc:creator><![CDATA[.trion 0]]></dc:creator><pubDate>Sun, 27 Feb 2011 18:52:56 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 15:20:54 GMT]]></title><description><![CDATA[<p>Laut Standard funktioniert das nur wenn sich alle Teile in einer &quot;Übersetzungseinheit&quot; befinden.<br />
Dass es unter Linux funktioniert ist also reiner Zufall.</p>
<p>Ich habe mal vor sehr vielen Jahren etwas Ähnliches (automatische Registrierung für eine Factory) versucht und bin auch darauf hereingefallen. Beim Aufteilen des Projektes in unterschiedliche LIBs hat nichts mehr funktioniert <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027691</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027691</guid><dc:creator><![CDATA[MichelRT]]></dc:creator><pubDate>Mon, 28 Feb 2011 15:20:54 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 17:22:59 GMT]]></title><description><![CDATA[<p>Nimm DLLMain als Einstiegspunkt für die .dll<br />
<a href="http://msdn.microsoft.com/en-us/library/ms682583%28v=vs.85%29.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/ms682583(v=vs.85).aspx</a></p>
<p>Ansonsten spricht auch nichts gegen eine normale init-funktion.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027742</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027742</guid><dc:creator><![CDATA[[[global:former_user]]]]></dc:creator><pubDate>Mon, 28 Feb 2011 17:22:59 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 19:01:41 GMT]]></title><description><![CDATA[<p>.trion schrieb:</p>
<blockquote>
<p>Kann man den Linker dazu bringen, die .o-Dateien einzeln mit dem Programm zu binden anstatt die Tabellen zu verwenden, oder gibt es vielleicht eine ganz andere Lösung für das Problem?</p>
</blockquote>
<p>Ich kenne folgenden Workaround:</p>
<pre><code class="language-cpp">// DeineLibrary.h --------------------------------------------

namespace Detail {

class Initializer;
Initializer const&amp; GetInitializer();

namespace {

Initializer const&amp; g_initializer = GetInitializer();

} // namespace

} // namespace Detail

// DeineLibrary.cpp ------------------------------------------

namespace Detail {

class Initializer {
    // ...
};

Initializer const&amp; GetInitializer()
{
    static Initializer s_initializer;
    return s_initializer;
}
</code></pre>
<p>So wie ich das verstehe, ist dann auch laut Standard garantiert, dass s_initializer in GetInitializer() immer konstruiert wird, auch wenn g_initializer nirgends referenziert wird.<br />
Wobei ... dass es laut Standard garantiert ist, heisst natürlich nicht, dass es auch überall wirklich funktioniert <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/2027788</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027788</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 28 Feb 2011 19:01:41 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 19:02:32 GMT]]></title><description><![CDATA[<p>Scorcher24 schrieb:</p>
<blockquote>
<p>Ansonsten spricht auch nichts gegen eine normale init-funktion.</p>
</blockquote>
<p>Hihi, doch. Dass man sie aufrufen muss <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2027789</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027789</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 28 Feb 2011 19:02:32 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 20:13:25 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>Ich kenne folgenden Workaround.....</p>
</blockquote>
<p>Du bist ein Gott! Das hat mich 2 Tage gekostet <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="😉"
    /> Läuft einwandfrei.</p>
<p>Für Copy&amp;Paste-freudige, das sind meine Initialisierermakros:</p>
<pre><code class="language-cpp">#define declare_initializer(identifier) \
	class identifier { \
		public: \
			identifier(); \
	}; \
	identifier const &amp; get##identifier(); \
	namespace { identifier const &amp; ref##identifier  = get##identifier(); } 

#define implement_initializer(identifier) \
	identifier const &amp; get##identifier() { \
		static identifier instance; \
		return instance; \
	} \
	identifier::identifier()
</code></pre>
<p>Für einen neuen Initialisierer:</p>
<pre><code class="language-cpp">// In einem Header, der irgendwo im Zielprojekt eingebunden wird
declare_initializer(MyInitializer);

// In der Library
implement_initializer(MyInitializer)
{
	// Code
}
</code></pre>
<p>Finalisierer funktionieren analog, nur muss man dabei den Destruktor statt den Konstruktor definieren.</p>
<p><strong>Edit: Kommando zurück</strong>, geht doch ein bisschen anders</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027799</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027799</guid><dc:creator><![CDATA[.trion 0]]></dc:creator><pubDate>Mon, 28 Feb 2011 20:13:25 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 19:46:21 GMT]]></title><description><![CDATA[<p>Reicht eigentlich auch eine globale Funktion, oder brauchts die Klasse (abgesehen von evtl. nützlichem Initialisierungscode im Konstruktor)?</p>
<pre><code class="language-cpp">const Initializer&amp; GetInitializer(); // wie gehabt

namespace
{ 
    const Initializer&amp; ref = GetInitializer();
}
</code></pre>
<p>Und muss <code>GetInitializer()</code> ausserhalb des anonymen Namensraums stehen? Besteht damit nicht nur die Gefahr eines potentiellen Namenskonflikts?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027806</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027806</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 28 Feb 2011 19:46:21 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 20:07:28 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/21207">@.trion</a>:<br />
Wenn ich mich richtig erinnere sind sowohl die Header als auch der anonyme Namespace nötig.</p>
<p>Die Header deswegen, damit man in jeder Übersetzungseinheit wo die Library XYZ benutzt wird, ein eigenes Ding (statische Variable) hat, dessen Initialisierung dazu führt, dass die GetInitializer() Funktion ausgeführt wird. (D.h. natürlich diese Header muss dann von allen Headern der Library XYZ includiert werden, sonst funktiert der Trick ja nichtmehr)</p>
<p>Ohne diesen Trick könnte (dürfte, laut Standard) der Compilier/Linker wieder die ganze Initializer-Instanz weglassen, so lange keine Funktionen aus der Übersetzungseinheit der Library in der die Initializer-Instanz definiert ist aufgerufen wird.</p>
<p>Also konkret, wenn du dein &quot;refFoo&quot; in foo.cpp definierst, der Anwender aber keine einzige Funktion aus foo.cpp aufruft, dann kann (darf) der Compiler foo.cpp einfach ganz weglassen, inklusive &quot;refFoo&quot;.<br />
Wenn das OK ist, dann ... ist es OK <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>Allerdings gibt es Fälle wo es nicht OK ist, und dann kann man mit eben diesem Trick arbeiten.</p>
<p>Achja... die Notwendigkeit des anonymen Namespace ergibt sich aus der Notwendigkeit der Header: ohne den hätte man nämlich ein mehrfach definiertes Symbol. (Man könnte natürlich &quot;static&quot; statt einem anonymen Namespace verwenden, aber ich verwende halt in solchen Fällen immer anonyme Namespaces)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027820</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027820</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 28 Feb 2011 20:07:28 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 20:18:20 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Reicht eigentlich auch eine globale Funktion?</p>
</blockquote>
<p>Die läuft wie gesagt Gefahr, wegoptimiert zu werden.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/21207">@.trion</a>:<br />
Wenn ich mich richtig erinnere sind sowohl die Header als auch der anonyme Namespace nötig.</p>
</blockquote>
<p>Fehler meinerseits, hat wegen einer falschen Linkereinstellung so ausgesehen als würde es funktionieren. Ist oben gefixt und geht jetzt.<br />
Danke nochmal.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027828</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027828</guid><dc:creator><![CDATA[.trion 0]]></dc:creator><pubDate>Mon, 28 Feb 2011 20:18:20 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 20:20:54 GMT]]></title><description><![CDATA[<p>.trion schrieb:</p>
<blockquote>
<p>Die läuft wie gesagt Gefahr, wegoptimiert zu werden.</p>
</blockquote>
<p>Nein, ich meine eine Funktion (halt wie die <code>static</code> -Memberfunktion), keine Variable. Warum sollte die eher wegoptimiert werden als die Memberfunktion?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027830</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027830</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 28 Feb 2011 20:20:54 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 20:35:35 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/12954">@Nexus</a>:<br />
Für Initialisierung braucht man eigentlich keine Klasse, da tut's eine freie Funktion die einen Dummy-Wert zurückgibt, den man dann zur Initialisierung einer Hilfsvariable verwendet. Allerdings wird die Funktion ja mehrfach aufgerufen, d.h. man müsste dann selbst checken ob es der erste Aufruf ist oder ein &quot;redundanter&quot;.</p>
<p>Und für Cleanup braucht man sowieso ne Klasse.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027840</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027840</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 28 Feb 2011 20:35:35 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 22:30:40 GMT]]></title><description><![CDATA[<p>Okay, danke.</p>
<p>Zur Initialisierung globaler Variablen habe ich im C++-Standard bisher nur das gefunden:</p>
<p>§3.6.2/1 Initialization of non-local objects schrieb:</p>
<blockquote>
<p>Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initializationtakes place. Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types (3.9) with static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic initialization takes place. <strong>Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit.</strong></p>
</blockquote>
<p>Heisst das nicht, dass globale Objekte (&quot;static storage duration&quot;) mit dynamischer Initialisierung innerhalb einer ÜE initialisiert werden <em>müssen</em>, und zwar in der Deklarationsreihenfolge? Oder ist das eher so zu verstehen, dass <em>wenn</em> sie initialisiert werden, die Reihenfolge eingehalten werden muss? Oder hat das überhaupt nichts damit zu tun?</p>
<p>Ich habe nämlich ebenfalls so eine Initialisierung vor. Die SFML-Bibliothek hat auch sowas mit dem klassischen Ansatz (alles in .cpp-Datei) gelöst und es scheint nicht wirklich Probleme zu geben...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027902</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027902</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 28 Feb 2011 22:30:40 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Mon, 28 Feb 2011 23:27:47 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Okay, danke.</p>
<p>Zur Initialisierung globaler Variablen habe ich im C++-Standard bisher nur das gefunden:</p>
<p>§3.6.2/1 Initialization of non-local objects schrieb:</p>
<blockquote>
<p><strong>Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initializationtakes place.</strong> Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types (3.9) with static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic initialization takes place. <strong>Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit.</strong></p>
</blockquote>
<p>Heisst das nicht, dass globale Objekte (&quot;static storage duration&quot;) mit dynamischer Initialisierung innerhalb einer ÜE initialisiert werden <em>müssen</em>, und zwar in der Deklarationsreihenfolge? Oder ist das eher so zu verstehen, dass <em>wenn</em> sie initialisiert werden, die Reihenfolge eingehalten werden muss? Oder hat das überhaupt nichts damit zu tun?</p>
</blockquote>
<p>Also so, wie ich das sehe kommt da der erste Satz (fett) zum tragen. Das heisst, dass sie <strong>immer</strong> 0 Initialisiert werden. Dass es so ist merkt man ja auch, dass die statischen Sachen im .bss Segment liegen, welches ja 0 Initialisiert ist. Oder verstehe ich dich mal wieder falsch? <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/2027937</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027937</guid><dc:creator><![CDATA[drakon]]></dc:creator><pubDate>Mon, 28 Feb 2011 23:27:47 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Tue, 01 Mar 2011 00:15:51 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/12954">@Nexus</a>:<br />
Das von dir Zitierte ist ja soweit schön und auch kein Problem. Um die Reihenfolge geht es hier ja nicht.</p>
<blockquote>
<p>Oder ist das eher so zu verstehen, dass <em>wenn</em> sie initialisiert werden, die Reihenfolge eingehalten werden muss?</p>
</blockquote>
<p>Ja, genau das ist das Problem.</p>
<p>Lies mal zwei Punkte weiter unten:</p>
<p>§3.6.2/3 schrieb:</p>
<blockquote>
<p>It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of<br />
namespace scope is done before the first statement of main. <strong>If the initialization is deferred to some point<br />
in time after the first statement of main, it shall occur before the first use of any function or object defined<br />
in the same translation unit as the object to be initialized.</strong></p>
</blockquote>
<p>Das impliziert, dass das Objekt <em>gar nicht</em> initialisiert werden muss, wenn nie Funktionen oder Objekte aus der Translation Unit aufgerufen/verwendet werden.</p>
<p>D.h. ...</p>
<p>Unproblematisch:</p>
<pre><code class="language-cpp">// in einem .cpp File:

namespace {

Foo g_somethingThatBarNeeds = MakeFoo();

} // namespace

Bar::Bar() // &quot;use of a function&quot; -&gt; g_somethingThatBarNeeds muss initialisiert worden sein bevor Bar::Bar() läuft (*)
{
    m_magicValue = g_somethingThatBarNeeds.GetMagicValue(); // ... d.h. wir können es hier Gefahrlos verwenden
}

//*: ausgenommen Bar::Bar wird selbst während der Initialisierung eines &quot;object with static storage duration defined in namespace scope&quot; aufgerufen,
//   dann haben wir das allseits beliebte &quot;initialization order fiasco&quot; und alles geht den Bach runter :^)
</code></pre>
<p>Unproblematisch deswegen, weil g_somethingThatBarNeeds ja nicht gerbaucht wird, so lange keine &quot;Bar&quot; erzeugt werden. Und wenn &quot;Bar&quot; erzeugt werden ist auch garantiert dass g_somethingThatBarNeeds initialisiert wird.</p>
<p>Problematisch:</p>
<pre><code class="language-cpp">// in einem .cpp File:

namespace {

class MyFactory { ... };

int RegisterMyFactory()
{
    static MyFactory fac;
    ::RegisterFactory(&amp;fac);
}

int g_registerHelper = RegisterMyFactory();

} // namespace
</code></pre>
<p>Problematisch deswegen, weil es hier u.U. gar keine Funktionen in der Translation Unit gibt, die <em>direkt</em> von aussen aufgerufen werden dürfen/können.<br />
Die Absicht wäre hier RegisterMyFactory() nur wegen der Nebeneffekte (nämlich das Registrieren der Factory) auszuführen. Wenn der Compiler aber meint, kann er die Initialisierung von g_registerHelper einfach weglassen, da ja nie Funktionen aus der Übersetzungseinheit aufgerufen werden.</p>
<p>Ich kenne zwar keine Implementierung die den Standard soweit ausreizt dass die Initialisierung <em>nach</em> dem ersten Statement von main() passiert. Allerdings gibt es viele die eben das was ganz wegoptimiert werden kann auch ganz wegoptimieren.</p>
<p>Das ist grundsätzlich auch OK, da der Linker dadurch Teile verwerfen kann, die nicht gebraucht werden. Nur führt es eben auch dazu, dass das Registrieren von MyFactory so wie im Beispiel oben nicht funktioniert.</p>
<p>Als Workaround packen wir eine dynamisch initialisierte Variable in jede Übersetzungseinheit, in der Code aus unserer Library verwendet wird. Da wir die Header-Files unserer Library kontrollieren geht das einfach, wir machen einfach ein &quot;mylib/common.h&quot; das von allen andere &quot;mylib/*.h&quot; Files inkludiert wird, und da drin steht der Code den ich hier ursprünglich gepostet habe.</p>
<p>Natürlich gibt es auch wieder Fälle wo selbst das nicht funktioniert, nämlich wenn wir nicht wollen/nicht erzwingen können dass ein Clientprogramm so ein Headerfile inkludiert. z.B. weil die .lib bloss wie im &quot;MyFactory&quot; Beispiel ein Plugin registrieren soll, und wir sie nur beim Linken angeben wollen/können. Das lässt sich über Standard-C++ dann nichtmehr erschlagen.</p>
<p>Ich hab's nicht ausprobiert, aber bei MSVC könnte es sein dass man das Wegoptimieren von solchen Variablen über</p>
<pre><code class="language-cpp">#pragma comment(linker, &quot;/include:__mySymbol&quot;)
</code></pre>
<p>verbieten kann.<br />
Also verbieten kann man es damit sicher, aber was ich nicht weiss, ist, ob es reicht wenn das in der .lib steht, oder ob dieses #pragma im Code der .exe/.dll stehen müsste. Wenn letzteres, dann wäre es für das worum es hier geht ja wieder witzlos.</p>
<p>Achja, falls jmd. weiss ob/wie man das &quot;Behalten&quot; einer Variable mit GCC erzwingen kann... wäre auch interessant.</p>
<p>p.S.:<br />
Der Workaround verlässt sich auch darauf, dass der Compiler/Linker genau das nicht macht was er dürfte, aber kein mir bekannter Compiler/Linker wirklich macht: die Initialisierung zu verzögern. In einigen Fällen wäre das nämlich genau so ein Problem, da die Initialisierung dann zu spät erfolgen würde. Aber wie gesagt: ich kennen keine Implementierung die das macht. Falls jemand eine kennt: bitte melden <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2027947</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027947</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 01 Mar 2011 00:15:51 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Tue, 01 Mar 2011 00:25:27 GMT]]></title><description><![CDATA[<p>@ drakon: Die Null-Initialisierung ist für den Fall hier nicht interessant, weil eben die Nebeneffekte (aufgerufene Funktion mit Registrierung) dadurch nicht zum Tragen kommen. Im Prinzip ist der Wert der initialisierten Variable egal, nur der Prozess der Initialisierung an sich ist relevant.</p>
<p>@ hustbaer: Danke für die Erläuterungen. Den Punkt habe ich sogar auch noch gesehen, aber mir nichts weiter dabei gedacht. Aber eigentlich ist es logisch... Normalerweise versuche ich auch, globale Variablen und frühzeitige Initialisierung genau wegen solcher Dinge zu vermeiden. Aber ab und zu ist das Ganze einfach zu praktisch <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>Allerdings könnte man manche Fälle auch lösen, indem man bei der ersten Verwendung einer Funktion die Initialisierung vornimmt (über eine funktionslokale <code>static</code> -Variable). Vielleicht sollte ich mir das überlegen... Ein <code>static bool</code> in einer Funktion hat wahrscheinlich nicht einmal ein verstecktes <code>if (__initialized)</code> , oder? (Bin mir gerade nicht sicher, ob das auch unter die normale <em>static storage duration</em> geht oder wieder zu irgendeinem Spezialfall gehört)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027954</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027954</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Tue, 01 Mar 2011 00:25:27 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Tue, 01 Mar 2011 01:24:36 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/12954">@Nexus</a>:<br />
Ein &quot;static bool&quot; in einer Funktion wird nur dann kein &quot;if (!initialized)&quot; haben, wenn es konstant initialisiert wird.<br />
Allerdings wüsste ich nicht wozu man so ein static bool jetzt bräuchte. Ausser um seinen Code thread-<strong>un</strong>safe zu machen.</p>
<p>Verwende gleich das &quot;Meyers Singleton&quot;, das ist wenigstens mit GCC thread-safe.<br />
Bzw. nimm folgenden Code (der vom Prinzip her das selbe macht wie das &quot;Meyers Singleton&quot;, nur ohne Singleton *g*)</p>
<pre><code class="language-cpp">int MyInitFunction()
{
   // ...
   return 42;
}

void MyPublicFunction()
{
    static int const s_myInitDummy = MyInitFunction();
    // ...
}
</code></pre>
<p>s_myInitDummy muss hier ein &quot;if (!initialized)&quot; vom Compiler verpasst bekommen, sonst würde es ja immer wieder überschrieben, und das erlaubt der Standard nicht. Dadurch sparst du dir selbst das entsprechende &quot;if&quot; zu schreiben, und bekommst von GCC wie schon gesagt auch threadsicheren Code geschenkt.</p>
<p>Ansonsten kann man boost::call_once verwenden um es unabhängig vom Compiler thread-safe zu machen.</p>
<p>Aber davon abgesehen</p>
<blockquote>
<p>Allerdings könnte man manche Fälle auch lösen, indem man bei der ersten Verwendung einer Funktion die Initialisierung vornimmt (über eine funktionslokale static-Variable). Vielleicht sollte ich mir das überlegen...</p>
</blockquote>
<p>Wenn das geht, dann ist ja alles wunderbar.<br />
Der hier diskutierte Workaround ist vor allem für Fälle gedacht, wo das nicht funktioniert, weil man Dinge vor Programmstart erledigen möchte. z.B. das Registrieren von Plugins/Modulen.</p>
<p>Bzw. allgemein Fälle, wo man die Nebeneffekte braucht, bevor eine Funktion aufgerufen wird deren Code man anfassen will/kann/darf.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2027961</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2027961</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 01 Mar 2011 01:24:36 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Tue, 01 Mar 2011 16:24:17 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>Allerdings wüsste ich nicht wozu man so ein static bool jetzt bräuchte. Ausser um seinen Code thread-<strong>un</strong>safe zu machen.<br />
[...]<br />
s_myInitDummy muss hier ein &quot;if (!initialized)&quot; vom Compiler verpasst bekommen, sonst würde es ja immer wieder überschrieben, und das erlaubt der Standard nicht. Dadurch sparst du dir selbst das entsprechende &quot;if&quot; zu schreiben, und bekommst von GCC wie schon gesagt auch threadsicheren Code geschenkt.</p>
</blockquote>
<p>Ich meinte genau sowas wie <code>s_myIntDummy</code> , aber halt ein <code>bool</code> (spielt ja keine Rolle). Ok, jetzt sehe ich auch, dass <code>bool</code> im dem Zusammenhang verwirrend ist, sorry. Ist so eine <code>static</code> -Konstante auf gcc nun threadsafe oder nicht? Denn irgendwie sehen deine Aussagen für mich wie ein Widerspruch aus <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>Konkret brauch ich das für einen Zufallsgenerator, dessen Seed beim Starten automatisch gesetzt werden soll. Da wäre Threadsicherheit wahrscheinlich nicht schlecht. Allerdings müsste ich dann auch noch einiges mehr threadsicher machen...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2028280</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028280</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Tue, 01 Mar 2011 16:24:17 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Tue, 01 Mar 2011 19:10:05 GMT]]></title><description><![CDATA[<p>Ich dachte du willst das &quot;if (!initialized)&quot; selbst schreiben (wegen bool und so, ja, war verwirrend). Das wäre dann nicht threadsafe, es sei denn du kümmerst dich selbst darum (Mutex oder so).</p>
<p>Wenn du es nicht selbst schreibst, sondern eine function-local static Variable verwendest, dann macht der Compiler es für dich. Und GCC macht es threadsafe. MSVC nicht.</p>
<p>Was der aktuelle C++0x Draft dazu sagt weiss ich nicht sicher. Ich <em>glaube</em> der sieht das so wie GCC es sieht, nämlich dass es threadsafe sein muss.</p>
<blockquote>
<p>Konkret brauch ich das für einen Zufallsgenerator, dessen Seed beim Starten automatisch gesetzt werden soll. Da wäre Threadsicherheit wahrscheinlich nicht schlecht.</p>
</blockquote>
<p>Zufallsgenerator mach ich immer als Instanzen, keine globalen Funktionen. Daher gibt's das Problem auch nicht.</p>
<p>Ansonsten ist thread-local Storage angesagt. Sonst kann ein Thread durch das Ziehen von Zahlen aus dem RNG die Sequenz die ein anderer Thread bekommt beeinflussen. -&gt; nicht gut.</p>
<p>p.S.: und mit thread-local Storage ist thread-safety bei der Initialisierung dann wieder kein Problem, da je eh jeder Thread seine eigenen Variablen hat.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2028356</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028356</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 01 Mar 2011 19:10:05 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Wed, 02 Mar 2011 16:49:14 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>Zufallsgenerator mach ich immer als Instanzen, keine globalen Funktionen. Daher gibt's das Problem auch nicht.</p>
</blockquote>
<p>Ja, wäre sicher flexibler, gerade wenn man an verschiedenen Orten voneinander unabhängige Zufallszahlen haben will. Allerdings brauch ich oftmals nur kurz in einem temporären Ausdruck eine Zufallszahl, dafür immer vorher ein Objekt anzulegen ist unpraktisch und liefert auch schlechte Zufallszahlen, wenn er erst gerade mit dem Seed initialisiert wurde. Oder man hätte halt zusätzlich eine globale Instanz, wobei dann wieder das Problem auftritt.</p>
<p>Wie machst du das, findest du immer einen genügend grossen Kontext, in dem du so ein RNG-Objekt anlegst, oder hast du dann auch häufig lokale &quot;Wegwerf-Objekte&quot;?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2028832</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028832</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 02 Mar 2011 16:49:14 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Wed, 02 Mar 2011 17:00:52 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Allerdings brauch ich oftmals nur kurz in einem temporären Ausdruck eine Zufallszahl, dafür immer vorher ein Objekt anzulegen ist unpraktisch und liefert auch schlechte Zufallszahlen, wenn er erst gerade mit dem Seed initialisiert wurde.</p>
</blockquote>
<p>Ja, unpraktisch. Ich habe gerne ein globales Objekt.</p>
<p>Aber daß der frisch geseedete Zufallszahlengwenerator schlechten Zufall liefert, sehe ich jetzt noch nicht.</p>
<pre><code class="language-cpp">int getSeed(){
   static int seed=time(0);//beim ersten mal uhrzeit lesen
   ++seed;//bei mehreren aufrufen unique machen
//nicht schlampig verwürfeln, dazu ist der Zufallszahlengenerator besser geeignet
   return seed;
}

Random::Random(){
   x=getSeed();
   this-&gt;rand();//die angekündigte initiale Verwürfelung
}
unsigned int Random::rand(){
  x=(x*17+5)%1000;//oder bessere Formel!
  return x;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2028840</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028840</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Wed, 02 Mar 2011 17:00:52 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Wed, 02 Mar 2011 17:05:35 GMT]]></title><description><![CDATA[<p>Meine Überlegung ist halt, dass Zufallszahlengeneratoren ihre Stärken (z.B. Einhalten einer gegebenen Verteilung, geringe Korrelation) vor allem dann ausspielen, wenn eine grössere Sequenz eingesetzt wird. Einzelne, frisch geseedete Zufallszahlen müssen diese Eigenschaften ja nicht zwingend erfüllen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2028845</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028845</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 02 Mar 2011 17:05:35 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Wed, 02 Mar 2011 17:13:44 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Meine Überlegung ist halt, dass Zufallszahlengeneratoren ihre Stärken (z.B. Einhalten einer gegebenen Verteilung, geringe Korrelation) vor allem dann ausspielen, wenn eine grössere Sequenz eingesetzt wird. Einzelne, frisch geseedete Zufallszahlen müssen diese Eigenschaften ja nicht zwingend erfüllen.</p>
</blockquote>
<p>Ich erwarte, daß die geringe Korrelation zwischen zwei aufeinanderfolgenden Zahlen zu erwarten ist. Deswegen mache ich nur ein rand() im Konstruktor. Ich verlasse mich darauf, daß der Generator recht ordentlich ist, und halte rand(); für nicht schlechter als rand();rand();rand();. Höchstens besser.</p>
<p>Aber hast recht, die nachgewiesenen Qualitäten des Generators sind bei meiner angedachten Benutzungsart nicht mehr da. Zum Beispiel die unglaubliche Periodenlänge des Mersenne Twisters muß ja weg sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2028849</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028849</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Wed, 02 Mar 2011 17:13:44 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Wed, 02 Mar 2011 17:20:58 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Wie machst du das, findest du immer einen genügend grossen Kontext, in dem du so ein RNG-Objekt anlegst</p>
</blockquote>
<p>Genau das.<br />
Wobei das in meinen Projekten immer recht einfach war, weil nur an wenigen Stellen wirklich Zufallszahlen gebraucht wurden. Dafür hab' ich schon manchmal verschiedene unabhängige Sequenzen gebraucht, daher würde ich auch nicht (ausschliesslich) mit einem globalen Generator arbeiten wollen.</p>
<blockquote>
<p>oder hast du dann auch häufig lokale &quot;Wegwerf-Objekte&quot;?</p>
</blockquote>
<p>Nö, das wäre mit den Generatoren die wir verwenden (Mersenne Twister) und mit der Art wie wir den Seed holen (CryptGenRandom) auch VIEL zu teuer.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2028855</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028855</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Wed, 02 Mar 2011 17:20:58 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Wed, 02 Mar 2011 17:29:41 GMT]]></title><description><![CDATA[<p>Ich frage mich halt einfach, ob man bei</p>
<pre><code class="language-cpp">void Func()
{
    Randomizer r;
    Use(r.Random());
}
</code></pre>
<p>nicht lieber</p>
<pre><code class="language-cpp">void Func()
{
    static Randomizer r;
    Use(r.Random());
}
</code></pre>
<p>einsetzen würde (von Threadsicherheit mal abgesehen)? Denn auch wenn man mehrere unabhängige <code>Randomizers</code> jeweils am Anfang verwürfelt, ist die aus verschiedenen <code>Randomizer</code> -Aufrufen resultierende Gesamtsequenz unschön. Es könnte ja sein, dass z.B. immer nur jede Sekunde so ein Aufruf stattfindet, und abhängig von der Qualität des Seeders eine unregelmässige Verteilung oder so auftritt.</p>
<p>Man könnte zwar argumentieren, dass in so einem Fall ein einzelner <code>Randomizer</code> benutzt werden sollte (wie im Code mit <code>static</code> ), aber dann hat man eben wieder einen Vorteil weniger durch die unabhängigen Objekte.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2028859</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028859</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 02 Mar 2011 17:29:41 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Wed, 02 Mar 2011 17:32:07 GMT]]></title><description><![CDATA[<p>@ hustbaer:<br />
Okay. Ja, mir scheint sowohl globale als auch unabhängige lokale RNGs haben ihre Vorteile. Vielleicht sollte ich so eine Klasse einrichten und davon eine globale Instanz erzeugen. Diese wird dann benutzt wenn nötig, und in den Fällen mit grösserem Kontext kann ich direkt neue Instanzen einsetzen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2028860</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028860</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 02 Mar 2011 17:32:07 GMT</pubDate></item><item><title><![CDATA[Reply to Globale Variablen in statischen Bibliotheken on Wed, 02 Mar 2011 17:46:39 GMT]]></title><description><![CDATA[<p>Wie wär's mit</p>
<pre><code class="language-cpp">void Foo::Func()
{
   Use(m_rng.Get());
}

// oder
template &lt;class G&gt;
void Func(G&amp; rng)
{
   Use(rng.Get());
}

// oder
void Func(AbstractRng&amp; rng)
{
   Use(rng.Get());
}
</code></pre>
<p>?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2028865</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2028865</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Wed, 02 Mar 2011 17:46:39 GMT</pubDate></item></channel></rss>