![](/img/trans.png)
[英]Qt/C++ memory leak with QThread and QPainter::drawText()
[英]How do I destroy the QPainter object / Get rid of drawText() memory leak?
我正在尝试减少大型应用程序的内存泄漏。 使用valgrind,我在调用QPainter
类的drawText()
函数时也看到了许多内存泄漏实例。 根据我读过的一些消息来源,它可能是一个Qt
bug,但我想也许我可以通过破坏QPainter
对象来解决它,正如文档所说 - >“记住在绘制后销毁QPainter
对象。 “
这是valgrind日志的一个实例,其中drawText()
导致泄漏:
127971 ==00:00:05:31.916 24132== 68,594 (768 direct, 67,826 indirect) bytes in 2 blocks are definitely lost in loss record 4,979 of 4,982
127972 ==00:00:05:31.916 24132== at 0x4C2683D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
127973 ==00:00:05:31.916 24132== by 0x81861FF: ft_mem_qalloc (in /usr/lib64/libfreetype.so.6.6.2)
127974 ==00:00:05:31.916 24132== by 0x8186242: ft_mem_alloc (in /usr/lib64/libfreetype.so.6.6.2)
127975 ==00:00:05:31.916 24132== by 0x81876BE: FT_New_Library (in /usr/lib64/libfreetype.so.6.6.2)
127976 ==00:00:05:31.916 24132== by 0x81819C3: FT_Init_FreeType (in /usr/lib64/libfreetype.so.6.6.2)
127977 ==00:00:05:31.916 24132== by 0x54E4667: ??? (in /usr/lib64/libQtGui.so.4.7.1)
127978 ==00:00:05:31.916 24132== by 0x54E4A64: QFontEngineFT::init(QFontEngine::FaceId, bool, QFontEngineFT::GlyphFormat) (in /usr/lib64/libQtGui.so.4.7.1)
127979 ==00:00:05:31.916 24132== by 0x54DE0B5: QFontEngineX11FT::QFontEngineX11FT(_FcPattern*, QFontDef const&, int) (in /usr/lib64/libQtGui.so.4.7.1)
127980 ==00:00:05:31.916 24132== by 0x542EE80: ??? (in /usr/lib64/libQtGui.so.4.7.1)
127981 ==00:00:05:31.916 24132== by 0x543721A: QFontDatabase::load(QFontPrivate const*, int) (in /usr/lib64/libQtGui.so.4.7.1)
127982 ==00:00:05:31.916 24132== by 0x5414D46: QFontPrivate::engineForScript(int) const (in /usr/lib64/libQtGui.so.4.7.1)
127983 ==00:00:05:31.916 24132== by 0x5429FDD: QFontMetricsF::leading() const (in /usr/lib64/libQtGui.so.4.7.1)
127984 ==00:00:05:31.916 24132== by 0x534ED45: ??? (in /usr/lib64/libQtGui.so.4.7.1)
127985 ==00:00:05:31.916 24132== by 0x534FCBD: QPainter::drawText(QRect const&, int, QString const&, QRect*) (in /usr/lib64/libQtGui.so.4.7.1)
127986 ==00:00:05:31.916 24132== by 0x5863AC: gui::base::Printer::printTitle() (in /home/bed/workspace/tasks/MemProfile/MemoryProfiling/build-pc-debug/src/application-ui)
127987 ==00:00:05:31.916 24132== by 0x585559: gui::base::Printer::run() (in /home/bed/workspace/tasks/MemProfile/MemoryProfiling/build-pc-debug/src/application-ui)
127988 ==00:00:05:31.916 24132== by 0x5D49A5D: ??? (in /usr/lib64/libQtCore.so.4.7.1)
127989 ==00:00:05:31.916 24132== by 0x7620A3E: start_thread (in /lib64/libpthread- 2.11.3.so)
127990 ==00:00:05:31.916 24132== by 0x738067C: clone (in /lib64/libc-2.11.3.so)
如果在堆栈上创建QPainter对象(即不使用new
),则如文档中所述:
void SimpleExampleWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setPen(Qt::blue);
painter.setFont(QFont("Arial", 30));
painter.drawText(rect(), Qt::AlignCenter, "Qt");
}
然后QPainter对象在超出范围时将被销毁(在上面的例子中:在函数的末尾)。 文档提到您需要小心删除QPainter对象的原因是因为Qt本身不会这样做,这与许多Qt小部件管理有点不同。
所以,假设你动态分配了这个对象:
void SimpleExampleWidget::paintEvent(QPaintEvent *)
{
QPainter* painter = new QPainter(this);
painter->setPen(Qt::blue);
painter->setFont(QFont("Arial", 30));
painter->drawText(rect(), Qt::AlignCenter, "Qt");
// Delete object, since Qt wont do it for you:
delete painter;
}
Qt告诉您,您负责清理QPainter对象,在我们的示例中,使用delete
命令完成。 但是,如果你使用这种方法,你可以考虑把它放在智能指针中,即: boost::scoped_ptr<QPainter> painter = new QPainter(this);
void SimpleExampleWidget::paintEvent(QPaintEvent *)
{
boost::scoped_ptr<QPainter> painter = new QPainter(this);
painter->setPen(Qt::blue);
painter->setFont(QFont("Arial", 30));
painter->drawText(rect(), Qt::AlignCenter, "Qt");
}
现在,至于正确的方式。 这取决于,如果您在本地创建QPainter对象,您需要多久创建一次QPainter对象,如示例中所示? 如果这会导致开销,请考虑将QPainter创建为成员变量,然后重复使用它。 (但是,如果你担心速度:“早期优化永远不是一个好主意”是应该致力于内心的事情)。
如果使用new
动态分配内存,请记住您也负责删除它。 如果您只是在堆栈中创建它,就像在最顶层的示例中一样,您不必担心,因为它会在退出创建它的范围时被销毁。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.