簡體   English   中英

如何銷毀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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM