[C++]Static member var construction

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • NC83
  • Registratie: Juni 2007
  • Laatst online: 21-08 21:44
Wat ik wil is een Factory object waarbij op app start up time objecten geregistreerd worden bij de factory zodat deze RTTI aangemaakt kunnen worden.

Om dit voor elkaar te krijgen heeft iedere class een static member variable die tijdens zijn constructie een singleton aanroept en daar een templated creation function achter laat met een string en RTTI informatie over dat object.

*snip*

Dit werkt allemaal goed echter worden niet alle objecten geregistreerd die zouden moeten worden geregistreerd. Alle objecten die ik wil registreren bevaten de correcte macros, ben ik hier tegen een C runtime probleem aan het aanlopen of is er gewoon iets mis met de code.

[ Voor 18% gewijzigd door Creepy op 17-03-2010 15:26 ]

ex-FE Programmer: CMR:DiRT2,DiRT 3, DiRT Showdown, GRID 2, Mad Max


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Kun je je daadwerkelijke probleem wat meer isoleren? Bijvoorbeeld met een voorbeeld waarbij het niet goed gaat.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Even zo uit mijn hoofd en zonder de code regel voor regele na te gaan (het kan dat ik het mis heb). Het klinkt eng. Je weet namelijk nooit wanneer statics constructed worden, dat ligt niet vast in de standaard. Waarschijnlijk worden een aantal van die static constructed voordat je singleton constructed is oid.

Ja, een minimaal voorbeeld zou helpen...

[ Voor 6% gewijzigd door Zoijar op 17-03-2010 15:12 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zijn singletons zijn function-static, dat zou dus altijd* goed moeten gaan.
C++:
1
Singleton & getInstance() { static Singleton instance; return instance; }


*behalve met multithreaded code ;)

[ Voor 13% gewijzigd door .oisyn op 17-03-2010 15:14 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Nu online

Creepy

Tactical Espionage Splatterer

Zou je je relevante code gewoon in je post willen stoppen? Mocht de code eens op een andere plek komen te staan, of mocht je het zelf online weghalen, dan blijft het topic toch nog steeds goed leesbaar in de toekomst.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • NC83
  • Registratie: Juni 2007
  • Laatst online: 21-08 21:44
In dit geval werkt het niet
Waarbij deze code een "ApplicationSetting" string uit een Xml file haalt
C++:
1
2
3
4
5
6
7
8
9
10
            DeserialisableSetting* setting = (DeserialisableSetting*)ObjectFactory::getInstance().createObject(element->Value());
            if (setting && setting->m_rttiInfo.IsDerived(DeserialisableSetting::m_rttiInfo))
            {
                setting->deserialise(element);
                SettingsManager::getInstance().setSetting(setting);
            }
            else
            {
                DLTRACEERRORC(m_errorLog, "Couldn't create setting for: %s, make sure there is a known class for this setting", element->Value());
            }


De functie om een om een object te creeeren is
C++:
1
2
3
4
5
6
7
8
9
    void* createObject(const String& className)
    {
        objectCreationFunction* creator = ClassRegistrySingleton::getInstance().getCreationFuntion(className.getString());
        if (creator)
        {
            return (**creator)();
        }
        return 0;
    }


Dit is de code om een creation function te krijgen
C++:
1
2
3
4
5
6
7
8
9
    objectCreationFunction* getCreationFuntion(std::string classID)
    {
        STROCFIT iterator = m_strOCFs.find(classID);
        if (iterator != m_strOCFs.end())
        {
            return &iterator->second;
        }
        return 0;
    }


Deze klasse wordt geprobeert om aan te maken
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class ApplicationSetting : public DeserialisableSetting
{
    DL_DECLARE_CLASS(ApplicationSetting, DeserialisableSetting)
public:
    ApplicationSetting();
    ~ApplicationSetting();

    void deserialise(TiXmlElement* element);
protected:
private:
    String m_appName;
    String m_windowName;
};

in CPP
DL_IMPLEMENT(ApplicationSetting, DeserialisableSetting);


Deze macros zijn vereenvoudigd zodat alleen het ClassRegistration gedeelte te zien is met de daar bijhoorende code
C++:
1
2
3
4
5
6
7
8
#define DL_DECLARE_CLASS(CLASS, BASECLASS) \
    public:\
    typedef BASECLASS Super;\
    static const ClassRegistrator s_registration##CLASS;\
    static CLASS* CreateObject() { return new CLASS(); }

#define DL_IMPLEMENT(CLASS, BASECLASS)\
    const ClassRegistrator CLASS::s_registration##CLASS(&CLASS::m_rttiInfo, #CLASS, &ObjectFactory::objectCreationFunctionTemplate<CLASS>)

De registratie wordt hierdoor gedaan:
C++:
1
2
3
4
5
6
7
8
class ClassRegistrator
{
public:
    ClassRegistrator(const RTTI* classType, const char* classID, objectCreationFunction ocf)
    {
        ClassRegistrySingleton::getInstance().addRegistration(classType, classID, ocf);
    }
};

C++:
1
2
3
4
5
    void addRegistration( const RTTI* classType, const char* classID, objectCreationFunction ocf)
    {
        m_rttiOCFs.insert(RTTIOCFPAIR(classType, ocf));
        m_strOCFs.insert(STROCFPAIR(classID, ocf));
    }


Wat er gebeurt tijdens runtime is dat setting altijd een nulpointer is. De code om een settings file in te lezen gebeurt tijdens de initialisatie van de applicatie, en als ik het goed begrijp is dit nadat alle class statics zijn gecreerd.
Als ik een debug run doe en kijk wanneer addRegistration wordt aangeroepen voor class waarbij het werkt gebreurt dit voordat main van de applicatie wordt aangeroepen, ik snap niet waarom dit niet voor alle objecten gebeurt want de techniek die ik probeer te gebruiken leunt daar nogal zwaar op.
Callstack voor een Object
code:
1
2
3
4
5
6
7
8
9
>   DLExampleApplication_debug.exe!ClassRegistrator::ClassRegistrator(const RTTI * classType=0x00698b50, const char * classID=0x0065d2ec, void * (void)* ocf=0x004c6bbe)  Line 71   C++
    DLExampleApplication_debug.exe!`dynamic initializer for 'Object::s_registrationObject''()  Line 3 + 0x37 bytes  C++
    msvcr90d.dll!_initterm(void (void)* * pfbegin=0x00658294, void (void)* * pfend=0x00658fc8)  Line 903    C
    DLExampleApplication_debug.exe!__tmainCRTStartup()  Line 497 + 0xf bytes    C
    DLExampleApplication_debug.exe!wWinMainCRTStartup()  Line 399   C
    kernel32.dll!754b3677()     
    [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]  
    ntdll.dll!77039d72()    
    ntdll.dll!77039d45()


Voor een RenderSetting class die niet veel anders is dan de ApplicationSetting class gaat het wel gewoon goed. Het enige verschil tussen de twee is dat RenderSetting niet in een eigen header en CPP is gedefinieerd

Na wat debuggen, kan dit te maken hebben met hoe files worden geinclude?

ex-FE Programmer: CMR:DiRT2,DiRT 3, DiRT Showdown, GRID 2, Mad Max


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zou het eventueel kunnen dat de RenderSettings code geheel wordt verwijderd omdat er geen referenties naar zijn? Al lijkt me dat wat onwaarschijnlijk, tenzij hij in een library staat oid.

Overigens is het registrar, niet registrator ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • NC83
  • Registratie: Juni 2007
  • Laatst online: 21-08 21:44
Nee want dat object wordt ook aangemaakt hier is trouwens het settings bestand dat wordt in gelezen.
XML:
1
2
3
4
<xml>
  <RenderSetting name="render_settings" resolution_width="1600" resolution_height="1024" use_cg="false" renderer="1"/>
  <ApplicationSetting name="application" app_name="DL Example Application" window_name="DL Game Window" />
</xml>


Dit project wordt wel als een .lib gecompiled en dan gebruikt in een ander project die de EXE maakt.

RenderSetting wordt aangemaakt en bevat de informatie die ik verwacht, en als ik de ApplicationSetting in Settings.h plaats wordt deze ook aangemaakt.
En in de initialisatie van een Window wordt er een pointer van ApplicationSetting gemaakt, RenderSetting wordt echter nergens gerefereerd omdat ik nog niet zo ver was, maar zou in de RenderSystem init moeten worden gebruikt.

ex-FE Programmer: CMR:DiRT2,DiRT 3, DiRT Showdown, GRID 2, Mad Max


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het zit in een lib, wat betekent dat de linker daar object files uit gaat halen op basis van external references die nog unresolved zijn. Als de initialisatiecode van de RenderSettings in een object file staat die verder niet direct of indirect wordt gebruikt door de uiteindelijke executable dan linkt de linker dat object file dus ook niet mee, en runt er geen constructor van de static bij startup. Dat is echt het enige wat ik nu zo zou kunnen bedenken dat er aan de hand is.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • NC83
  • Registratie: Juni 2007
  • Laatst online: 21-08 21:44
Dat is in ieder geval iets dat ik kan testen, en klinkt erg waarschijnlijk wat er aan de hand is. So unity files it is then.

Ik gok dat dat het ook is want zodra die pointer gederefernced wordt werkt het wel, thanks.

[ Voor 27% gewijzigd door NC83 op 17-03-2010 21:35 ]

ex-FE Programmer: CMR:DiRT2,DiRT 3, DiRT Showdown, GRID 2, Mad Max

Pagina: 1