此代码是否提供内存泄漏?

时间:2015-11-03 20:11:01

标签: c++ qt memory-leaks valgrind

最后我已经安装了Ubuntu并设置了Qt + Valgrind以防止内存泄漏,这是我在Windows中无法做到的。所以我无法理解这段代码是否提供内存泄漏?事实上,Valgrind说我只有500多个问题,但没有泄漏。我

#include <QWidget>
#include <QFrame>
#include <QVBoxLayout>
#include <QApplication>

int main(int argc, char *argv[])

{
    QApplication a(argc, argv);

    QWidget * wdgt = new QWidget;  //this line should be the cause of leakage 
                                   //if it exist (as far as i know)
    QVBoxLayout *layout = new QVBoxLayout;
    QFrame * frame = new QFrame;

    frame->setFrameStyle(QFrame::Panel | QFrame::Plain);
    frame->setLineWidth(5);
    layout->addWidget(frame);

    wdgt->setLayout(layout);
    wdgt->setFixedSize(800,600);
    wdgt->show();

    return a.exec();
}

3 个答案:

答案 0 :(得分:8)

请参阅此帖子:Creating and deallocating a Qt widget object

它解释了如果一个Qt对象有一个父对象,它将在父对象被销毁时自动删除。

在您的代码中:

  • wdgtlayout的父级,因为您wdgt->setLayout(layout)
  • wdgtframe的父级,因为您layout->addWidget(frame)layout的父级是wdgt。正如thuga评论的那样,布局将所有权传递给他们自己的父母。

在您的代码中,只有wdgt是孤儿(没有Qt父级自动将其删除)。

要解决这个问题,你可以给他一个父母:

QWidget * wdgt = new QWidget(&app);

因此wdgtapp的孩子,然后在app被销毁时自动删除。

或自行删除:

int main(int argc, char *argv[])
{
    ...
    int res = a.exec();
    delete wdgt; // this will delete wdgt, but also frame and layout
    return res;
}

或者,fianlly,将其创建为一个对象,以便在超出范围时将其删除:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget wdgt;

    QVBoxLayout *layout = new QVBoxLayout;
    QFrame * frame = new QFrame;

    frame->setFrameStyle(QFrame::Panel | QFrame::Plain);
    frame->setLineWidth(5);
    layout->addWidget(frame);

    wdgt.setLayout(layout);
    wdgt.setFixedSize(800,600);
    wdgt.show();

    return a.exec();
}

顺便说一句,请注意,如果您执行QVBoxLayout *layout = new QVBoxLayout(wdgt),则无需执行wdgt->setLayout(layout)。所以这两段代码是等价的:

QVBoxLayout *layout = new QVBoxLayout(wdgt); // parenting upon construction

与:

相同
QVBoxLayout *layout = new QVBoxLayout; // no parent
wdgt->setLayout( layout ); // reparenting

答案 1 :(得分:0)

是的,您的代码会泄漏内存,因为您使用new创建对象而不使用Qt的内存管理。

转到

QApplication a(argc, argv);
QWidget * wdgt = new QWidget(&app);
QVBoxLayout *layout = new QVBoxLayout(wdgt); // optional, setLayout does that
QFrame * frame = new QFrame(layout); // optional, addWidget does that

使用Qt的内存管理。

或者,您可以使用C ++ 11共享指针:

QApplication a(argc, argv);
std::shared_ptr<QWidget> wdgt = std::make_shared<QWidget>();

QVBoxLayout *layout = new QVBoxLayout;
QFrame * frame = new QFrame;

只要共享指针的最后一个用户超出范围,您的对象就会自动删除。

答案 2 :(得分:0)

您的代码会泄漏内存,但首先您不应该在您需要关注资源泄漏的地方编写代码。让编译器为您处理:

// main.cpp
#include <QtWidgets>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    QWidget widget;
    QVBoxLayout layout(&widget);
    QFrame frame;

    frame.setFrameStyle(QFrame::Panel | QFrame::Plain);
    frame.setLineWidth(5);
    layout.addWidget(&frame);

    widget.setFixedSize(800,600);
    widget.show();
    return a.exec();
}