Aufruf einer Methode vor der Initialisierung von statischen Variablen



  • Hey hey,

    ich habe mal eine systemnahe Frage zu C und C++.

    Und zwar habe ich zur Zeit eine eigene Speicherverwaltung in C++ implementiert.
    Durch das Überladen der new und delete Operatoren werden alle Objekte, welche mit new erzeugt werden, in der Speicherverwaltung in einem statischen Speicherbereich abgelegt und durch den überladenen delete Operator werden alle
    angeforderten Speicherbereiche wieder freigegeben

    Intern in der Speicherverwaltung gibt es unter anderem die Methoden <allocateMem> und <freeMem>. Bevor diese Methoden aufgerufen werden können, muss der statische Speicherbereich der Speicherverwaltung initialisiert werden. Diese Initialisierung geschieht momentan sofort nach dem Starten von <main()> durch das Starten einer Methode <initMemHandler>

    Es ist ja nun auch möglich, statische Objekte mit new zu initialisieren. Wie ist es nun möglich, dass die Initialisierungsmethode vor dem ersten new aufgerufen wird.

    Eine Möglichkeit ist ein Flag zu setzen und die Initialisierungsfunktion im überladenen New-Operator aufzurufen. Aber hierfür ist dann bei jedem new
    eine Überprüfung notwendig, was nicht wirklich optimal ist. Gibt es noch eine weitere Möglichkeit, fällt irgendeinem etwas ein?

    Ok, Danke schonmal!
    Mit freundlichen Grüßen
    sevenWaysToLove



  • Du könntest ein Objekt einer Klasse, die den Speicher verwaltet, als Meyers-Singleton (das Singleton ist eine funktionslokale statische Variable) implementieren. Denn funktionslokale statische Variablen werden beim ersten Aufruf der Funktion (egal von wo) konstruiert.

    // MemoryManagementGuard sei eine Klasse, die im Konstruktor den Speicherbereich initialisiert
    
    MemoryManagementGuard& MemoryManagementGuard::Instance()
    {
        static MemoryManagementGuard instance;
        return instance;
    }
    
    void* allocateMem(size_t length)
    {
        return MemoryManagementGuard::Instance().allocateMem(length);
    }
    

    So wird beim ersten Aufruf von MemoryManagementGuard::Instance() ein Objekt der Klasse initialisiert. Wenn Du den Ctor, Copy-Ctor und Copy-Operator der Klasse noch private machst ist auch garantiert dass niemand sonst so ein Objekt anlegt.

    EDIT:
    Worauf man noch achten sollte ist, dass in multithreaded Umgebungen die Methode Instance() mindestens einmal aufgerufen werden sollte, bevor irgendein weiterer Thread neben dem Hauptthread gestartet wird.



  • Schreib dir doch eine Speicherverwaltungsklasse, wo du deine statischen Variablen und statische Methoden, auf die deine überschriebenen Operatoren zugreifen, drin hast. Da du nur ein Speicherverwaltungsobjekt brauchst, kann man da gut das Singleton Pattern anwenden und es bei Zugriff über die statischen Methoden ggf. einmalig initialisieren.

    class MemManager 
    {
    private: 
     static MemManager* mng;
     MemManager() : ;  //Konstruktor privat
    public:
    
    static MemManager* getThis(){ if (!mng) mng = new MemManager(); return mng; }
    static getmem()  //wird vom Überschriebenen new() aufgerufen
      {
       MemManager* m = getThis(); //...
      }
    // usw.
    };
    

    /edit: mist, wieder zu lahm ^^



  • Ob es so gut ist, einen Memorymanager der new und delete überschreibt, mit new zu allokieren, um sicherzustellen, dass new und delete korrekt funktionieren? 🤡



  • da wird sich auch mit Sicherheit die althergebrachte Version von new nutzen lassen...



  • Für sowas würde ich wenn dann placement new verwenden, und den Speicher z.B. mit HeapAlloc(GetProcessHeap(), ...) anfordern. Das geht immer, ohne irgendwelche Initialisierungen.



  • Hey hey,

    die Lösung mit dem Meyers-Singleton gefällt mir richtig gut!

    Danke 🙂

    MfG
    sevenWaysToLove



  • @sevenWaysToLove:
    dir ist schon klar dass dieses "meyers singleton" a) nicht threadsafe ist und b) genau das gleiche wie wenn du selbst bei jedem Funktionsaufruf "if (!initialized) initialize();" schreibst... ?



  • hustbaer schrieb:

    ...genau das gleiche wie wenn du selbst bei jedem Funktionsaufruf "if (!initialized) initialize();" schreibst... ?

    Wahrscheinlich gefällt es ihm deswegen so gut .... 😉

    Gruß,

    Simon2.



  • Ja, aber eine OOP-Variante ist einfach schicker ... 🙂

    Im Endeffekt habe ich es jetzt auch so geloest ... 🙂



  • Ich hatte das deswegen erwähnt:

    sevenWaysToLove schrieb:

    Eine Möglichkeit ist ein Flag zu setzen und die Initialisierungsfunktion im überladenen New-Operator aufzurufen. Aber hierfür ist dann bei jedem new
    eine Überprüfung notwendig, was nicht wirklich optimal ist

    Wenn das eine nicht optimal ist, ist es das andere auch nicht, weil das eine gleich dem anderen ist. Sozusagen.
    Blubb.



  • In dem Sinne halte ich aber "macht der Compiler für mich" für optimaler als "mach ich selbst". Und irgendwer muss sowieso prüfen ob schon initialisiert wurde 😉


Anmelden zum Antworten