static class member deallocation



  • Hallo,

    1. Ich habe eine private static pointer class member variable.
    m_geometry
    2. Für die Speicher allocation bzw deallocation sind functionen vorhanden
    cvCreateMat
    cvReleaseMat

    Während der declaration der statischen Variable im *.cpp file kann ich
    gleichzeitig die speicherallocation durchführen:

    CvMat* MultiCameraModel::Camera_Param_Common_System::m_geometry = 
    cvCreateMat(3,3,CV_64F);
    

    Die frage ist nun: Wo oder wie ich die deallocation durchführe
    (cvReleaseMat) um memory leaks zu verhindern.

    Einen Ansatz, den ich bis jetzt verfolgt habe ist:
    Mit einer statischen variable die Object instanzen zählen, und wenn nach
    meinem "Object Instanz counting" der destructor der letzten instanz
    aufgerufen wird den Speicher der statische variable m_geometry mit
    cvReleaseMat freigeben.

    Dieser Ansatz ist jedoch nicht ideal :

    _ kompliziert | fehleranfällig
    _ Die semantic von static wird verändert: "sichtbar während mindestenz eine
    Instanz existiert" anstatt "sichtbar während der gesamten Programmlaufzeit"

    Mit dem "Object Instanz counting" existieren im moment immer noch memory
    leaks! Ich führe das auf die spezielle funktion des Copy,- und
    Assignment-Operatoren zurück.

    Gut, nun zu meiner Frage. Wenn es möglich ist eine statische variable zu
    initialisieren (bei der declaration) dann gibt es sicher eine "stelle"
    (oder methode) an der man statische variablen deinitialisieren kann.
    Vielleicht einen speziellen destruktor für statische Variablen.

    Grüsse,
    Gerd

    Der Anschaulichkeit halber hier noch der Quelltext (ohne "Object Instanz counting")

    //HEADER
    
    namespace MultiCameraModel
    {
    
    class Camera_Param_Common_System
    {
    public:
    	Camera_Param_Common_System(void);
    	~Camera_Param_Common_System(void);
    
    	Camera_Param_Common_System(const 
    MultiCameraModel::Camera_Param_Common_System& another);
    	const  MultiCameraModel::Camera_Param_Common_System& operator=(const 
    MultiCameraModel::Camera_Param_Common_System& right);
    
    private:
    	//static members
    	static CvMat* m_geometry;
    };
    
    }
    
    //SOURCE
    
    //DEFINITION FOR STATIC VARIABLES
    CvMat* MultiCameraModel::Camera_Param_Common_System::m_geometry = 
    cvCreateMat(3,3,CV_64F);  
    
    MultiCameraModel::Camera_Param_Common_System::Camera_Param_Common_System(void)
    {
    }
    
    MultiCameraModel::Camera_Param_Common_System::~Camera_Param_Common_System(void)
    {
    }
    
    MultiCameraModel::Camera_Param_Common_System::Camera_Param_Common_System(const 
    MultiCameraModel::Camera_Param_Common_System& another)
    {
    }
    
    const  MultiCameraModel::Camera_Param_Common_System& 
    MultiCameraModel::Camera_Param_Common_System::operator=(const 
    MultiCameraModel::Camera_Param_Common_System& right)
    {
    }
    


  • Smart Pointer?



  • bei beendigung des prozesses gibt das betriebssystem allen vom prozess allozierter speicher automatisch frei.



  • smart pointers?

    ist nicht ganz so einfach (mal davon abgesehen das ich mich mit smart pointern nicht so auskenne).

    Habe etwas darüber gelesen:
    1. bei der variablen m_geometry handelt es sich um einen pointer auf eine struct. Möglicherweise funktionieren smart pointer nicht mit structs, da constructor/destructor vorrausgesetzt werden?

    2. smart pointer != smart pointer. Es existieren sehr viele unterschiedliche und sehr spezialisierte implementationen dieses algorithmus. So weit ich das überflogen habe brauche ich einen mit "POW", da in meiner klasse copy,- bzw assignment-operatoren implementiert sind. Dieser ist schon beinahe als garbage collector zu bezeichnen, dieses beeinflusst mglw. die laufzeit.

    3. einen ähnlichen ansatz habe ich auch schon verfolgt: die object instanzen zählen, wenn der destructor der letzen instanz aufgerufen wird die statische variable deallokieren.
    -immer noch memory leaks (mglw. aufgrund der copy,- bzw assignment-operatoren)
    -die semantic von static wird verändert: "sichtbar während mindestenz eine
    Instanz existiert" anstatt "sichtbar während der gesamten Programmlaufzeit"

    Kannst du mir einen "smart pointer" empfehlen?



  • aUSER schrieb:

    Habe etwas darüber gelesen:
    1. bei der variablen m_geometry handelt es sich um einen pointer auf eine struct. Möglicherweise funktionieren smart pointer nicht mit structs, da constructor/destructor vorrausgesetzt werden?

    Klar funktionieren Smart Pointer mit Structs - der Compiler erstellt dir notfalls einen Default-Ctor und -Dtor, wenn du nichts eigenes geschrieben hast.

    2. smart pointer != smart pointer. Es existieren sehr viele unterschiedliche und sehr spezialisierte implementationen dieses algorithmus. So weit ich das überflogen habe brauche ich einen mit "POW", da in meiner klasse copy,- bzw assignment-operatoren implementiert sind. Dieser ist schon beinahe als garbage collector zu bezeichnen, dieses beeinflusst mglw. die laufzeit.

    Du hast nur ein einziges CvMat-Objekt für die gesamte Klasse, das braucht also weder zugewiesen noch kopiert zu werden. Was würde also in dem Zusammenhang dagegen sprechen, ein statisches Objekt statt eines Pointers zu verwenden?



  • Konfusius schrieb:

    bei beendigung des prozesses gibt das betriebssystem allen vom prozess allozierter speicher automatisch frei.

    warum muss man sich dann als c/c++ programmierer um speicherverwaltung kümmern?

    In meiner testumgebung läuft ein memory leak checker mit stack-trace, dieser meldet ein memory leak und gibt als ursprung die initialisierung der static variable an:

    //declaration und allocation
    CvMat* MultiCameraModel::Camera_Param_Common_System::m_geometry =
    cvCreateMat(3,3,CV_64F);

    ist auch logisch da die deallocattions-function für die struct nicht aufgerufen wurde. die pointer variable wurde freigegeben, jedoch nicht die daten auf die der pointer zeigt. folgender aufruf muss auf die allocation folgen um den speicher wieder freizugeben.

    cvReleaseMat( &MultiCameraModel::Camera_Param_Common_System::m_geometry );

    dieser aufruf fehlt in dem program. im destructor wäre ziemlich unsinnig, da es sich um eine static variable handelt. wo kann man den speicher für eine statische variable freigeben?

    Die Aussage stimmt natürlich für build in types (int, double ...)

    verwende selbst static int 'S : diese leaken nicht!

    bei selbstdefinierten types/objekten musst du dich selbst um die speicherverwaltung kümmern. Bei meiner static member variable handelt es sich um ein objekt aus der OpenCV library. CvMat ist eine struct. mit der funktion cvCreateMat wird die CvMat struct initialisiert (der speicher wird reserviert). auf jedes cvCreateMat muss ein cvReleaseMat folgen das den speicher wieder freigibt (wie bei new/delete)



  • Du müsstest die Aufrufe von Create bzw. Release in den Con/Destruktor einer Wrapper-Klasse packen, dann kannst du die Memory-Leaks auch abfangen:

    class CvMatPtr
    {
    public:
      CvMatPtr(int x,int y, CV_Mode m) : data(cvCreateMat(x,y,m)) {}
      ~CvMatPtr() { cvReleaseMat(data); }
      operator CvMat*() { return data; }
    private:
      CvMatPtr(const CvMatPtr&);
      CvMatPtr& operator=(const CvMatPtr&);
    
      CvMat* data;
    };
    
    class Param_System
    {
      ...
    private:
      static CvMatPtr m_geometry;
    };
    
    CvMatPtr Param_System::m_geometry(3,3,CV_64F);
    

    (Destruktoren von statischen Elementen werden am Programmende aufgerufen - und da m_geometry jetzt von einem sturen Pointer zu einem statischen Objekt aufgewertet wurde, kümmert es sich zum Abschied auch um die Ressourcen-Freigabe)



  • [/quote]Du hast nur ein einziges CvMat-Objekt für die gesamte Klasse, das braucht also weder zugewiesen noch kopiert zu werden. Was würde also in dem Zusammenhang dagegen sprechen, ein statisches Objekt statt eines Pointers zu verwenden?[/quote]

    du meintest wahrscheinlich auf dem heap bzw. stack das object anlegen.

    stack : Objekte die kurz leben. zum beispiel innerhalb einer methode
    speicher muss nicht explizit freigegeben werden
    heap : Objekte die eine längere lebenszeit haben (z.b. new/delete;malloc/free)

    für eine static variable scheint der stack nicht geeignet zu sein. Gut mal angenommen man macht es trotzdem. Wie

    CvMat ist eine struct. hier der code

    typedef struct CvMat
    {
    int type; /* CvMat signature (CV_MAT_MAGIC_VAL), element type and flags /
    int step; /
    full row length in bytes */

    int* refcount; /* underlying data reference counter */

    union
    {
    uchar* ptr;
    short* s;
    int* i;
    float* fl;
    double* db;
    } data; /* data pointers */

    #ifdef __cplusplus
    union
    {
    int rows;
    int height;
    };

    union
    {
    int cols;
    int width;
    };
    #else
    int rows; /* number of rows /
    int cols; /
    number of columns */
    #endif

    } CvMat;

    Ich weiss nicht wie man diese struct auf dem stack initialisiert?



  • aUSER schrieb:

    Du hast nur ein einziges CvMat-Objekt für die gesamte Klasse, das braucht also weder zugewiesen noch kopiert zu werden. Was würde also in dem Zusammenhang dagegen sprechen, ein statisches Objekt statt eines Pointers zu verwenden?

    du meintest wahrscheinlich auf dem heap bzw. stack das object anlegen.

    stack : Objekte die kurz leben. zum beispiel innerhalb einer methode
    speicher muss nicht explizit freigegeben werden
    heap : Objekte die eine längere lebenszeit haben (z.b. new/delete;malloc/free)

    für eine static variable scheint der stack nicht geeignet zu sein. Gut mal angenommen man macht es trotzdem. Wie

    Nein, statische Objekte befinden sich weder auf dem Heap noch auf dem Stack, sondern in einem eigenen Datensegment - die werden vor dem Start von main() initialisiert und irgendwo in der exit()-Behandlung wieder zerlegt.
    Der Pointer m_Geometry deiner Klasse ist so ein statisches Objekt, das, worauf er zeigt, liegt auf dem Heap.

    Und wie du diese automatische Initialisierung/Zerstörung nutzen kannst, habe ich etwas weiter oben vorgeführt. Alternative Lösung wäre es, der struct selber einen Konstruktor und Destruktor zukommen zu lassen und sie dann direkt zu erzeugen statt über Hilfsfunktionen:

    struct CvMat
    {
      ... //Elemente wie bisher
      CvMat(int x,int y,int t);//Initialisierung wie in cvCreateMat(...)
      ~CvMat();                //Aufräumen wie in cvReleaseMat(...)
    };
    

Anmelden zum Antworten