PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : when optimization goes bad?


muhkuh_rs
2006-02-14, 10:23:24
Hi,

folgendes Problem:

#include <list>

typedef void (*registerfunc)();

class CMgr
{
public:
static std::list<registerfunc> & GetRegisterList()
{
static std::list<registerfunc> registerlist;
return registerlist;
}

static bool Register(registerfunc func)
{
GetRegisterList().push_back(func);
return true;
}

};

template< class T> class THelper
{
public:
//virtual bool GetDummy() { return ms_bDummy; }

private:
static bool ms_bDummy;
};

template <class T>
bool THelper<T>::ms_bDummy=CMgr::Register(T::Register);


class CTest : public THelper<CTest>
{
public:
static void Register()
{
printf("Registering CTest\n");
}
};


Der Sinn des Ganzen soll irgendwann sein, bestimmte statische Funktionen von Klassen automatisch zu registrieren.

Das Problem dabei ist, dass der Compiler den statischen Member ms_bDummy nicht anlegt, vermutlich weil er der Meinung ist, dass er nicht gebraucht wird. Das ist ja so auch richtig, nur ist eben der ausgeführte code bei der Initialisierung von dummy das, worauf es mir ankommt. Ob das so glücklich gelöst ist, sei mal dahingestellt aber darf mir der Compiler das denn so einfach wegoptimieren? Das macht der MS Compiler von visual C++ 7.1 bei mir schon ohne dass Optimierungen an sind. Deswegen vermute ich, dass ich irgendwas übersehen habe. Wenn man den Kommentar vor GetDummy() entfernt, dann wird ms_bDummy angelegt. Wenn man dann noch Optimierungen einschaltet aber auch wieder nicht mehr.

Edit:
Typos, code berichtigt.

Demirug
2006-02-14, 11:11:38
Der Compiler verhält sich absolute korrekt.

Ohne die Zugriffsmethode (GetDummy) ist ms_bDummy eine member variable welche nur durch die Klasse selbst benutzt werden kann. Da dies aber niemals vorkommen kann wirft sie der Compiler einfach raus.

Mit dem Zugriffsmethode ist zwar die Variable erst mal vor dem rauswerfen geschützt aber beim Optimieren wird der Compiler feststellen das du GetDummy nie aufrufst. Deswegen wirft er zuerst diese Methode raus und dann im nächsten Schritt ist ms_bDummy wieder fällig weil es ja nun nicht mehr gebraucht wird.

muhkuh_rs
2006-02-14, 11:31:01
Der Compiler verhält sich absolute korrekt.

Ohne die Zugriffsmethode (GetDummy) ist ms_bDummy eine member variable welche nur durch die Klasse selbst benutzt werden kann. Da dies aber niemals vorkommen kann wirft sie der Compiler einfach raus.

Mit dem Zugriffsmethode ist zwar die Variable erst mal vor dem rauswerfen geschützt aber beim Optimieren wird der Compiler feststellen das du GetDummy nie aufrufst. Deswegen wirft er zuerst diese Methode raus und dann im nächsten Schritt ist ms_bDummy wieder fällig weil es ja nun nicht mehr gebraucht wird.

Sollte der Compiler nicht irgendwie mitbekommen, dass die Methode, die ms_bDummy initialisiert, selbst Änderungen an anderen statischen Variablen macht?

Demirug
2006-02-14, 11:37:58
Sollte der Compiler nicht irgendwie mitbekommen, dass die Methode, die ms_bDummy initialisiert, selbst Änderungen an anderen statischen Variablen macht?

Die Initialisierungs Methode wirft ja ja gar nicht raus. Er enfernt nur die initialisierung einer Variablen die niemals gelesen wird.

muhkuh_rs
2006-02-14, 11:55:28
Die Initialisierungs Methode wirft ja ja gar nicht raus. Er enfernt nur die initialisierung einer Variablen die niemals gelesen wird.

CMgr::Register(T::Register) wirf er nicht raus. Aber er führt es nicht aus. Aber die Ausführung von CMgr::Register(T::Register) würde Änderungen an anderen Variablen bedeuten, welche später im Programm gelesen werden. Deswegen dachte ich, der Compiler sollte mitbekommen, dass zwar ms_bDummy nicht gelesen wird, bei dessen Initialisierung aber andere Variablen verändert werden. Deswegen kann er zwar ms_bDummy entfernen, müsste aber CMgr::Register(T::Register) trotzdem ausführen. Vielleicht schreibt ja der Standard auch vor, dass bei der Initialisierung von statischen Variablen keine anderen statischen variablen verändert werden dürfen ...

Demirug
2006-02-14, 13:14:22
Die ganzen anderen statischen Variablen werden aber soweit ich das sehe auch nicht mehr benutzt. Ich will aber nicht ausschließen das er da etwas zu agressiv optimiert. Der ganze Konstruct ist ja auch etwas "heftig". Was für ein Pattern versuchst du denn damit zu implementieren?

muhkuh_rs
2006-02-14, 14:16:35
Ich hab noch ne main dazubebastelt, die die Liste der Funktionspointer ausgibt aber das ändert nichts. Ich versuche, dass Klassen sich automatisch durch Erben von einem Klassentemplate registrieren. Später sollen sich dann Objektinstanzen automatisch durch eine KlassenID erzeugen lassen.

Ich dachte, ich kann automatisch über Initialisierungen statischer Membervariablen eine Liste mit statischen classinfo structs aller im Projekt enthaltennen Klassen generieren lassen. Dann kann ich zur Laufzeit nach einer bestimmten Klassen-ID in den structs suchen und eine im struct vorhandene Create-Methode aufrufen.

Da es so nicht geht, muss ich wohl die Klassen leider selbst registrieren.