Variable trotz "volatile" wegoptimiert?



  • Morgen,

    ich hab das Gefühl, dass mir mein Compiler (ich nutze Visual Studio 2008) eine globale Variable wegoptimiert, obwohl ich sie als volatile deklariert habe... zumindest kann ich mir das ganze nicht anders erklären.

    Naja, ich erklär erstmal worums geht:
    Ich wollte ein möglichst simples Event-System in mein Projekt integrieren. Nachdem mir boost::signals jede Menge Linker-Fehler hingeschmissen hat, und ich mich lieber mit Programmier- als mit IDE-Problemen rumschlage, hab ich mir selber eine minimalistische Lösung geschrieben, die bisher eig. auch super funktioniert hat:

    Event.h

    template < typename T >
    	class Event
    	{
    		public:
    
    			//==========================================================
    			//	Constructors and Destructors
    			//==========================================================
    			inline Event()
    			{
    				Handler.resize(0);
    			}
    
    			inline ~Event()
    			{
    
    			}
    
    			//==========================================================
    			//	General Methods
    			//==========================================================
    			inline int				Connect( T handler )
    			{
    				Handler.push_back(handler);
    				return Handler.size();
    			}
    
    			inline void				Disconnect( T handler )
    			{
    				for ( vector<T>::const_iterator ci = Handler.begin();ci!=Handler.end();++ci)
    					if (*ci == handler )
    						Handler.erase(ci);
    			}
    
    		public:
    
    			vector<T>				Handler;
    	};
    
    	#define InvokeEvent(e,x) for ( uint i=0;i<e.Handler.size();i++ ) if (e.Handler[i]) e.Handler[i]##x;
    	#define RegisterForEvent(e,x) volatile int _##e##x = e.Connect(x);
    

    Benutzen tu ich das ganze dann z.B. so:

    main.cpp

    #include "Event.h"
    #include <iostream>
    
    //Event definieren
    Event < void (*)( int, int ) > TestEvent;
    
    int main()
    {
        int x = 1234;
        int y = 555;
    
        //Event aufrufen
        InvokeEvent( TestEvent, (x,y) )
        return 0;
    }
    
    void Blabla( int x, int y )
    {
        std::cout << "Funktion Blabla mit Parametern " << x << " und " << y << "aufgerufen!" << std::endl;
    }
    
    //Für Event registrieren
    RegisterForEvent( TestEvent, Blabla )
    

    Direkt mal vorneweg - ich weiß dass mir jeder C++ - Lehrer für die Vergewaltigung der Sprache bei InvokeEvent den Kopf einschlagen würde^^
    Der Vorteil der int-Variable bei RegisterForEvent ist eben, dass ich so Ereignisse beim Programmstart registrieren kann. Hat bisher auch gut funktioniert, nur bei einem einzigen Event scheint mir der Compiler die volatile int - Variable einfach wegzuoptimieren, wodurch die Handler-Funktion dann nicht registriert wird.

    Lustigerweise hab ich sogar mal versucht Optimierungen ganz auszuschalten - keine Veränderung. Ich bin mir trotzdem recht sicher, dass es an der Optimierung liegt, denn wenn ich die erzeugte volatile int _NAME - Variable nämlich irgendwo benutze, wo er sie auf keinen Fall wegoptimieren kann ( z.B. den Wert in einem cout << ausgeben ), dann funktioniert das ganze auch😮

    Meine Frage also: Wie kann ich meinen Compiler daran hindern, mir die Variable zu zerstören, ohne die einfache Syntax des Systems zu beeinträchtigen? Oder liegt es womöglich doch an etwas ganz anderem?

    Ich wäre über jede Hilfe dankbar.



  • der compiler optimiert hier vermutlich gar nichts weg.
    tippe eher auf den linker. der sieht dass die ganze translation-unit nicht vom programm referenziert wird, und linkt sie daher nicht mit. da die ganze TU wegfällt, fällt natürlich auch die hilfs-variable weg.

    bin mir auch grad nicht sicher ob überhaupt (vom standard aus) garantiert ist, dass eine globale variable in einer translation-unit überhaupt jemals initialisiert wird, so lange keine funktion in dieser translation-unit aufgerufen wird. mag sein dass das nur für static-variablen gilt. das standard-dokument hab ich auf dem computer wo ich grad schreibe auch nicht zur hand.

    wenn du damit weiter rumbasteln willst kannst du als erstes mal probieren die variable als "extern" zu definieren.
    wenn das nichts hilft musst du irgendwo im programm irgend eine funktion aus der translation-unit aufrufen um die es geht.
    oder sonst wie sicherstellen dass der linker sie nicht weglässt. MSVC hat hierzu z.b. eine option in den linker-einstellungen ob er dinge wegwerfen darf, und wie fein die päckchen für den linker geschnürt werden (ganze TU oder einzelne funktionen).



  • Im Beispiel lebt alles in der main.cpp.
    volatile ist hier nicht nötig.
    Bei mir klappt das Beispiel (mingw gcc 4.4.0), falls die Ausgabe

    Funktion Blabla mit Parametern 1234 und 555aufgerufen!
    

    sein soll.



  • Okay, es liegt wohl wirklich an der Translation Unit. Ich hab mal eine dummy-funktion in die cpp mit dem Event gepackt und aufgerufen - tadaa! es geht^^

    Jetzt wäre nur noch eine Universal-Lösung recht, wie ich dem Linker beibringe, mir die TU nicht zu verwerfen...

    1. extern hat nix gebracht
    2. Bei normalen Projekten gibts eine Option bei Optimierung "Verweise", bei der man "die Vernichtung von Daten, auf die nicht verwiesen wird" verhindern kann - allerdings hab ich das Ganze in einer statischen Bibliothek und da gibts die nicht -.-

    Wäre toll wenn jemand auch noch dafür eine Lösung hätte, aber wenn nicht ists auch nicht so tragisch.

    Und schonmal danke an hustbaer für die schnelle Hilfe!



  • Lösung kann ich dir leider keine anbieten - hab selbst schonmal nach einer Gesucht, aber nix gefunden.
    Ausser natürlich den offensichtlichen, also z.B. Init-Funktion verwenden und alles in der Init-Funktion verdrahten.


Anmelden zum Antworten