Worin besteht der Unterschied?



  • Hi zusammen.

    Ich habe eine Frage zu einem Algorithmus den ich programmiert habe:
    Der folgende Code arbeitet korrekt alle Phasen meines Algorithmus ab.

    int main()
    {
       GNG_Algorithm gng = GNG_Algorithm();
       gng.gng_initialize(100, 10, 2, 100, 10000, 0.2, 0.006, 50, 0.995, 0.5, "");	
    
       gng.gng_executeAlgorithm();
       gng.createClusterPool();
       ClusterPool clusterpool = gng.getClusterPool();
       return 0;	
    }
    

    Wenn ich nun aber folgendes versuche zu realisieren, also die Objekte global definiere:

    GNG_Algorithm gng;
    ClusterPool clusterpool;
    
    int main()
    {
       gng = GNG_Algorithm();
       gng.gng_initialize(100, 10, 2, 100, 10000, 0.2, 0.006, 50, 0.995, 0.5, "");	
    
       gng.gng_executeAlgorithm();
       gng.createClusterPool();
       clusterpool = gng.getClusterPool();
       return 0;	
    }
    

    Dann kann der Algorithmus nicht abgearbeitet werden.
    Ich vermute dass einige Objekte meiner Klasse bereits gelösct werden, obwohl sie noch in späteren Phasen des Algorithmus gebraucht werden.

    Kann mir vielleicht jemand erklären woran dies liegt?



  • Spielt es denn eine Rolle, ob gng oder clusterpool zuerst initialisiert werden? Denn die Initialisierungsreihenfolge ist bei globalen und statischen Objekten undefiniert.

    Gelöscht sollte nichts werden, die Objekte werden erst bei Programmende zerstört. Was geht denn nicht?



  • redbomber schrieb:

    Wenn ich nun aber folgendes versuche zu realisieren, also die Objekte global definiere:

    Wobei globale Objekte eh pfui sind.

    Ich nehme mal an, das GNG_Algorithm und ClusterPool keinen sauberen Kopierkonstruktor und Zuweisungsoperator besitzen.

    // Aufruf mit Standardkonstruktor
    GNG_Algorithm gng = GNG_Algorithm();
    
    // Gegenüber Standardkonstruktor und anschließenden Zuweisungsoperator
    GNG_Algorithm gng;
    gng = GNG_Algorithm();
    

    cu André



  • Wenn ich etwa auf eine Vector eines internen Objekts zugreife,
    so ist dieser leer.
    Obwohl er im dem entsprechendem Konstruktor befüllt wurde.



  • Wann greifst du zu?

    Zeig mal die Konstruktoren und den Zuweisungsoperator, die Memberdeklarationen wären auch nicht schlecht.



  • Spielt es denn eine Rolle, ob gng oder clusterpool zuerst initialisiert werden? Denn die Initialisierungsreihenfolge ist bei globalen und statischen Objekten undefiniert.

    Innerhalb einer Übersetzungseinheit ist das schon definiert. (Nämlich in der Reihenfolge der Deklaration).



  • drakon schrieb:

    Innerhalb einer Übersetzungseinheit ist das schon definiert. (Nämlich in der Reihenfolge der Deklaration).

    Danke für die Berichtigung, das war mir nicht bewusst. Ich dachte, damit hätte ich mal Probleme gehabt... Wahrscheinlich hab ich mich getäuscht. 😉

    Naja, besser, man verwendet erst gar keine globalen Variablen. 🙂



  • Nexus schrieb:

    drakon schrieb:

    Innerhalb einer Übersetzungseinheit ist das schon definiert. (Nämlich in der Reihenfolge der Deklaration).

    Danke für die Berichtigung, das war mir nicht bewusst. Ich dachte, damit hätte ich mal Probleme gehabt... Wahrscheinlich hab ich mich getäuscht. 😉

    Du wirst kaum nur eine Übersetzungseinheit gehabt haben. Das hat man selten in richtigen Projekten und dann hat man das Problem relativ schnell, dass dir Reihenfolge eine Rolle spielt..

    Aber das ist ja ein Grund, warum globals böse sind. 🙂



  • Der Grund für die globalen Variablen liegt darin,
    dass ich gerade versuche für meinen C++ Algorithmus einen Wrapper für D zu schreiben.

    Dabei muss ich alle benötigten C++ Schnittstellen-Methoden soweit vereinfachen, dass nur primitive Datentypen verwendet werden.

    Und dies wollte ich mit "dazwischengeschobenen" Methoden realisieren, welche eben nur primitive Datentypen verwenden.
    Aber das geht bisher leider noch nicht.



  • Vielleicht kann ich es nochmal etwas genauer erklären.
    Der ganze Algorithmus soll nur wenige Schnittstellen besitzen.
    Die Hauptklasse ist GNG_Algorithm, dessen Konstruktor wie folgt aussieht:

    GNG_Algorithm::GNG_Algorithm(){
    
    		connectionspool = ConnectionsPool();
    		connectionspool_ptr = &connectionspool;
    		nodepool = NodePool();
    		nodepool_ptr = &nodepool;
    		signals = Signals();
    		signals_ptr = &signals;
    		gng_parameters = GNG_Parameters();
    		gng_parameters_ptr = &gng_parameters;
    		clusterpool = ClusterPool();
    
    	}
    

    Wenn der Anwender den Algo ausführen möchte, erstellt er ein Object von dem GNG_Algorithm.

    GNG_Algorithm gng = GNG_Algorithm();
    

    Initialisiert diesen (Hier werden dann auch alle im Konstruktor angegeben Objekte initialisiert)

    gng.gng_initialize(...);
    

    und lässt ihn dann laufen.

    gng.gng_executeAlgorithm();
    

    Klappt auch alles wunderbar, wenn ich mein Objekt GNG_Algorithm lokal behalte.

    Nun kommt aber die Schnittstelle zu D ins Spiel.
    Hier darf ich nur noch primitive Datentypen als Parameter verwenden.
    Also kann ich mir in D ja auch nicht das Objekt GNG_Algorithm speichern.

    Also wollte ich einen Wrapper.cpp dazwischen setzen.
    Dieser enthält nur Methoden mit primitiven Datentypen. Innerhalb seiner Methoden greift er dann aber auf das
    Objekt GNG_Algorithm() zu.

    In der Theorie hoffentlich verständlich für euch.
    Praktisch funktionierts aber leider garnicht, da ständig auf Vektoren von untergeordneten
    Klassen zugegriffen wird, diese sind leer, obwohl sie eigentlich schon definiert wurden.



  • redbomber schrieb:

    Der Grund für die globalen Variablen liegt darin,
    dass ich gerade versuche für meinen C++ Algorithmus einen Wrapper für D zu schreiben.

    Dabei muss ich alle benötigten C++ Schnittstellen-Methoden soweit vereinfachen, dass nur primitive Datentypen verwendet werden.

    Und dies wollte ich mit "dazwischengeschobenen" Methoden realisieren, welche eben nur primitive Datentypen verwenden.
    Aber das geht bisher leider noch nicht.

    Sowas macht man typischerweise mit C-Funktionen und Handles auf die C++ Objekte, z.B.:

    //irgendwo im C++-Teil
    class MyVerySophisticatedCPPType
    {
        //:::
        void someFunc(ArgType someArgs);
    };
    
    //Interface (header)
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    typedef void* HandleType;
    typedef int ErrCode;
    
    HandleType createMyVerySophisticatedCPPType(ArgType args); //Ctor
    
    ErrCode someFunc(HandleType handle, ArgType args); //eine der publics
    
    void destroyMyVerySophisticatedCPPType(HandleType handle); //Dtor
    
    #ifdef __cplusplus
    }
    #endif
    
    //Impl.
    HandleType createMyVerySophisticatedCPPType(ArgType args)
    {
        return new MyVerySophisticatedCPPType(args);
    }
    
    ErrCode someFunc(HandleType handle, ArgType args);
    {
        reinterpret_cast<MyVerySophisticatedCPPType*>(handle)->someFunc(args);
    }
    
    void destroyMyVerySophisticatedCPPType(HandleType handle)
    {
        delete reinterpret_cast<MyVerySophisticatedCPPType*>(handle);
    }
    

    Nur so als Schema. Solche C-Funktionen kann man dann z.B. in D benutzen, aber auch in vielen anderen Programmiersprachen oder für dlls.


Anmelden zum Antworten