极简Qt程序存在内存泄漏问题

3

这是一个几乎最小的Qt程序,应该释放所有资源,包括内存:

#include <QApplication>
#include <QMainWindow>
#include <memory>

int main(int argc, char** argv) {
    QApplication app(argc, argv);
    std::unique_ptr<QWidget> wnd{new QWidget()};
    wnd->show();
    return app.exec();
} 

然而,valgrind指出:
LEAK SUMMARY:
   definitely lost: 979 bytes in 24 blocks
   indirectly lost: 7,858 bytes in 56 blocks
     possibly lost: 912 bytes in 19 blocks
   still reachable: 75,719 bytes in 1,080 blocks
                      of which reachable via heuristic:
                        newarray           : 832 bytes in 16 blocks
        suppressed: 0 bytes in 0 blocks
Rerun with --leak-check=full to see details of leaked memory

我本以为会得到“绝对丢失”和“间接丢失”的零值,但却获得了丢失的字节。为什么呢?是我错误地解释了valgrind的输出,还是我需要调用Qt的某些额外退出函数?


你的代码过度了。除非有充分的理由,否则不要通过指针持有小部件/ QObject。像所有其他使用 PIMPL 的 Qt 对象一样,QWidget 的大小为 void*通过值来持有它 - Kuba hasn't forgotten Monica
是的,Qt泄漏了那些内存,因为在终止进程时释放它会浪费CPU周期。 就我而言,它应该泄漏更多:每个这样的释放都是浪费。 您需要将未释放的分配作为Valgrind的异常添加。 这些是单次分配,它们不会随时间累积。 它们发生在启动时,并且完全正常。 - Kuba hasn't forgotten Monica
2个回答

2
这是一个错误的假设,即“正确/适当/任何你认为好的衡量标准”的代码不会泄漏内存。
有两种类型的泄漏内存:启动时或仅一次性分配,永远不会重复;和从可重复任意增加次数的分配中持续泄漏。后者是难以理解的,并且应该无情地打击,直到它们消失。
相反,释放启动内存是完全浪费的。将每个CPU周期都用于此操作是浪费的,因为下一件要发生的事情是进程终止,在此期间所有内存都以最节省循环和能源的方式释放。这些分配不是泄漏。它们需要添加到您的内存调试工具的异常列表中。
在进程终止之前释放每个内存块的狂热做法对于多次快速执行的应用程序的能源效率产生了明显的影响。对于许多Unix核心实用程序和构建工具(包括编译器)等常见的短暂进程,退出前的free浪费了全球各地许多火车车厢的煤,而这一趋势并没有放缓。
Valgrind是一种救星。但您不能像神一样崇拜其输出。不要根据Valgrind的输出开发软件,就好像它是一种货物崇拜。理解输出的含义,并相应地采取行动。

谢谢您的意见,但问题不在于缺少泄漏是好还是坏,而在于如何在Qt应用程序中实现零泄漏。无论如何,感谢您的评论,我已经得出了更好的问题表述:“valgrind抑制qt错误”,并立即得到了答案。 - olpa
1
@olpa,您不想要零泄漏。您想要的是在Valgrind报告中零泄漏。这两者之间有很大的区别。 - Kuba hasn't forgotten Monica

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接