【问题标题】:Qt/C++ memory leak with QThread and QPainter::drawText()Qt/C++ 内存泄漏与 QThread 和 QPainter::drawText()
【发布时间】:2011-08-10 14:39:05
【问题描述】:

我使用的是 Qt4.6,在 64 位 Linux 下编译的 32 位,并且有一个我无法弄清楚的令人费解的内存问题。我有一个包含 QLabel 的 QWidget。此 QLabel 用作每个重绘设置的绘画区域:

m_label->setPixmap(QPixmap::fromImage(image));

图像在小部件paintEvent中更新:

void MemTest::paintEvent(QPaintEvent* pEvent)
{
    // Wait for latest painting if not finished, then perform threaded repaint
    m_plotThread->wait();
    m_plotThread->start();
}

也就是说,绘制是使用 QThread 线程执行的,其中线程函数如下所示:

void PlotThread::run()
{
    // Lock the thread
    m_mutex.lock();

    // Image for painting
    QImage image(400, 300, QImage::Format_ARGB32);
    image.fill(0);

    // Create painter on the image
    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing, true);
    QFont font("Helvetica", m_textSize);
    painter.setFont(font);
    painter.setPen(QColor(255,0,0));
    painter.setBrush(QColor(130,150,255));

    // Draw some shapes
    painter.drawLine(0, 0, 400, 300);
    painter.setPen(QColor(40,30,30));
    painter.drawEllipse(15, 50, 130, 90);

    // Draw the text
    // !!! This causes memory leak !!!
    painter.drawText(QPoint(40, 100), "What's my problem?");

    m_mutex.unlock();

    // Send painted image through signal
    emit plotFinished(image);
}

一切都按预期工作,除了 drawText 导致严重的内存泄漏,在多次绘制后很容易检测到。该问题仅在绘制完成线程并使用 drawText 时出现。如果 drawText 被删除,或者如果它直接使用,而不是线程,在小部件paintEvent 中没有问题。例如使用drawLine、drawRect、drawEllipse等多线程绘制没有问题。

对这种行为有解释吗?而drawText函数如何多线程使用而不造成泄漏?

【问题讨论】:

  • 您是如何检测到内存泄漏的?
  • 我认为在 Qt 中不允许从非 GUI 线程进行绘画...
  • @Evan:确实有限制,但在大多数情况下是允许的(见答案)
  • @Bart:我还没有真正使用任何工具来跟踪泄漏。我只是在 Fedora 中使用系统监视器看到它,因为它是一个非常严重的泄漏......
  • 你可以使用 valgrind 来检测内存泄漏。我对 drawText() 也有同样的问题,valgrind 报告了很多泄漏... :(

标签: c++ multithreading qt memory-leaks


【解决方案1】:

虽然在非 GUI 线程中的 QImage 上支持大多数绘图操作,但在 X11 系统上有一个 supportsThreadedFontRendering 是否允许文本渲染:

http://doc.qt.nokia.com/4.7-snapshot/qfontdatabase.html#supportsThreadedFontRendering

我不确定您的系统上返回的标志是什么。但即使它说“真”,那么你的配置中可能有足够的黑魔法,它不会起作用。

有关 Qt 处理线程和绘制操作的细节的其他一些重要说明,请查看此处:

http://doc.qt.nokia.com/4.7-snapshot/threads-modules.html#painting-in-threads

【讨论】:

  • 非常感谢。我想确实有一些魔法,因为 QFontDatabase::supportsThreadedFontRendering() 返回 true 并且文本正确呈现,唯一的问题是内存......
  • 一般来说听起来很狡猾,可能最好避免,因为他们直截了当地说它不适用于某些安装。因此,如果 supportsThreadedFontRendering 为 false,您的应用程序要么具有替代实现,要么在这种情况下拒绝运行。我只想要一个代码路径,然后将 GUI 线程排队等待文本请求,或者找到另一种实现目标的方法。如果您的应用程序中的文本渲染很大(比如它是一个文字处理器),我可能会考虑使用 FreeType 而不是“膨胀”,以保持一致性和控制:en.wikipedia.org/wiki/FreeType
猜你喜欢
  • 1970-01-01
  • 2018-04-08
  • 2017-05-18
  • 2014-03-02
  • 1970-01-01
  • 2015-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多