Speichermanagement von Zeigern in QT5



  • Hallo,
    ich habe eine Frage zum Speichermanagement von Zeigern in QT5. In einem Udemy-Kurs wird folgender Code gezeigt:

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        QAction *quitAction=new QAction("Quit");
        connect(quitAction, &QAction::triggered, [=](){QApplication::quit();});
    
        QPushButton *button=new QPushButton("Hello!!", this);
        setCentralWidget(button);
        ...
        
    }
    
    MainWindow::~MainWindow()
    {
    }
    

    Mich stört, dass der Speicher auf den die beiden Zeiger zeigen nie gelöscht werden->Memoryleak(???). Müsste man die beiden Zeiger nicht ausserhalb der Methoden definieren und im Destruktor dann löschen?



  • Zumindestens für die Window-Elemente (wie z.B. QPushButton) nicht, denn der QMainWindow-Destruktor löscht rekursiv (per delete) alle Subelemente.

    Und für die QAction müßtest du diese ja noch z.B. einem QMenuoder QToolbar hinzufügen, um dem Anwender diese zur Verfügung zu stellen. Und auch dann würden diese vom Window-Destruktor automatisch mitgelöscht.

    s.a. Object Trees & Ownership



  • This post is deleted!


  • Ist jetzt etwas länger her, aber ich würde nicht davon ausgehen, dass das Zuweisen einer QAction die Ownership übernimmt. Die kann man ja auch mehreren Widgets zuweisen. Das sieht mir tatsächlich nach einem Memleak aus.



  • @Mechanics
    Auch QAction hat ein parent-Pointer im Konstruktor.

    https://doc.qt.io/qt-5/qaction.html#QAction

    We recommend that actions are created as children of the window they are used in. In most cases actions will be children of the application's main window.

    zu addAction:

    The ownership of action is not transferred to this QWidget.



  • @manni66 sagte in Speichermanagement von Zeigern in QT5:

    Auch QAction hat ein parent-Pointer im Konstruktor.

    Das ist mir schon klar. Das wird nur im gezeigten Code nicht übergeben.

    Beim zweiten Punkt war ich mir nicht sicher, danke für das Zitat.



  • OK, es sollte also

    QAction *quitAction = new QAction("Quit", this);
    

    lauten, damit kein Memory-Leak entsteht (wie beim QPushButton, wo ja auch this als parent übergeben wird),

    PS: Unter Profiling and Memory Checking Tools gibt es eine Liste von entsprechenden Tools.



  • Etwas offtopic, aber ich glaube nicht, dass das mit irgendwelchen Tools so einfach zu finden ist. Zumindest finde ich, dass es bei etwas komplexeren Programmen immer noch extrem kompliziert ist, Memory Leaks zu finden.
    Selbst mit den teureren Tools kommt man nicht so wirklich weiter... Der VS Memory Profiler taugt leider nicht sehr viel (ist in der Hinsicht aber auch nicht schlechter, als die anderen). AQTime haben wir eine ganze Weile eingesetzt, aber mit großen Programmen hatte das massiv Probleme, irgendwann wars nicht mehr einsetzbar. Und ich kann mich jetzt auch nicht dran erinnern, dass wir damit tatsächlich mal einen Memleak gefunden hätten. Die meisten Open Source Tools von der Liste hatten wir auch probiert. Am ehesten wird man noch mit lauter false positives zugemüllt.



  • Mir ist nicht klar, ob bei Qt bei der Übergabe des Parent dieser später den Speicher der untergeordneten Objekte wieder freigibt, wenn er gelöscht wird, es sieht für mich anhand der Codeschnipsel jedoch ganz danach aus.

    Nach meiner Erfahrung bieten sich bei Speicherallokationen in C++ std::unique_ptr bzw. std::shared_ptr am besten an, seitdem ich diese verwende, habe ich keinerlei Probleme mehr mit Speicherlecks.



  • @Burkhi sagte in Speichermanagement von Zeigern in QT5:

    Mir ist nicht klar, ob bei Qt bei der Übergabe des Parent dieser später den Speicher der untergeordneten Objekte wieder freigibt

    Ja.

    @Burkhi sagte in Speichermanagement von Zeigern in QT5:

    Nach meiner Erfahrung bieten sich bei Speicherallokationen in C++ std::unique_ptr bzw. std::shared_ptr am besten an, seitdem ich diese verwende, habe ich keinerlei Probleme mehr mit Speicherlecks.

    Ganz so einfach ist das nicht... Denk mal an eine Software in der Größenordnung 5-10 Mio Zeilen Code, über Jahrzehnte gewachsen, auch noch mit dutzenden 3rdparty Komponenten, die teilweise ganz unterschiedliche Speicherverwaltungsstrategien verfolgen. Dann teilweise auch noch sehr viele Querreferenzen (über viele Ecken), Caches usw. Und dann lässt du das auf einem Live Server paar Tage laufen, und hast das Gefühl, das verbraucht vielleicht etwas zu viel Speicher ^^
    Klar, in den letzten Jahren sind Memleaks viel seltener geworden, grad auch wegen den Smartpointern. Aber wenn wir doch mal irgendwo einen vermuten, ist es teilweise immer noch extrem aufwändig, den zu finden.


Log in to reply