调用函数500次后,获取Pixmap是一个空的pixmap. [英] Getting Pixmap is a null pixmap on calling a function 500 times

查看:217
本文介绍了调用函数500次后,获取Pixmap是一个空的pixmap.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在qt标签中显示图像.下面是我的代码:

I am showing a image in qt label. Below is my code:

void MyClass::onPushButtonClicked(QString myurl)
{
    this->setCursor(Qt::WaitCursor);
    ui.qtImageLabel->clear();
    qDebug()<<QTime::currentTime()<<"MyClass: onPushButtonClicked";
    QNetworkAccessManager *qnam_push_button_clicked_show_image;
    QNetworkReply *reply;
    QNetworkRequest request;
    request.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
    QUrl url(myurl);
    request.setUrl(url);
    qnam_push_button_clicked_show_image = new QNetworkAccessManager(this);
    if(qnam_push_button_clicked_show_image)
    {
        QObject::connect(qnam_push_button_clicked_show_image, SIGNAL(finished(QNetworkReply*)),
                         this, SLOT(onPushButtonClickedRequestCompleted(QNetworkReply*)));
        reply = qnam_push_button_clicked_show_image->post(request, url.encodedQuery());
        QEventLoop loop;
        QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
        loop.exec();
    }
}

void MyClass::onPushButtonClickedRequestCompleted(QNetworkReply *reply)
{
    qDebug()<<QTime::currentTime()<<"MyClass: onPushButtonClickedRequestCompleted request completed";
    if (reply->error() != QNetworkReply::NoError)
    {
        qDebug() << "Error in" << reply->url() << ":" << reply->errorString();
        this->setCursor(Qt::ArrowCursor);
        return;
    }
    QByteArray data = reply->readAll();
    QPixmap pixmap;
    pixmap.loadFromData(data);
    int width;
    int height;
    //application size can be changed
    QRect rec = QApplication::desktop()->screenGeometry();
    height = rec.height();
    width = rec.width();
    qDebug()<<QTime::currentTime()<<width<<","<<height;
    QSize *size = new QSize(width,height);
    if(size)
    {
        QPixmap scaledPixmap = pixmap.scaled(*size);
        ui.qtImageLabel->setPixmap(scaledPixmap);
    }
    if(size)
    {
        delete size;
        size = NULL;
    }
    data.clear();
    this->setCursor(Qt::ArrowCursor);
    reply->deleteLater();
    return;
}

单击按钮时,它将向服务器发送请求,并显示从服务器接收到的其他图像.如果不超过500次,则工作正常.如果超过该值,则会显示此错误

On clicking push button It will send a request to server and will show a different image received from server. It is working fine if it does't exceeds 500 times. If it exceeds that first this error has been shown

QPixmap::scaled: Pixmap is a null pixmap

,并且不显示图像.然后,如果有人再次发送图像请求,则会显示以下错误: Qt捕获了事件处理程序引发的异常.投掷 Qt不支持来自事件处理程序的异常.你必须 重新实现QApplication::notify()并在那里捕获所有异常.

and it doesn't show the image. Then if someone again sends a request for an image then it shows the following error: Qt has caught an exception thrown from an event handler. Throwing exceptions from an event handler is not supported in Qt. You must re implement QApplication::notify() and catch all exceptions there.

我没有得到上面代码中的错误.有人可以告诉我如何解决吗?

I am not getting what is the error in the above code. Can someone please tell me how to solve this?

推荐答案

明显的泄漏是qnam_push_button_clicked_show_image = new QNetworkAccessManager(this);,它在任何地方都没有均衡的删除. QNAM通常应创建一次,然后在应用程序的生命周期内重用,而不是为单个请求创建.因此,通过在类成员(与ui相同)中打开qnam_push_button_clicked_show_image,可以修复泄漏并提高代码效率.

The obvious leak is qnam_push_button_clicked_show_image = new QNetworkAccessManager(this);, which doesn't have a balanced delete anywhere. QNAMs should typically created once, then reused for the lifetime of the application rather than created for a single request. So by turning qnam_push_button_clicked_show_image in a class member (same as ui) you'll fix both your leak and improve the efficiency of the code.

也就是说,我不认为这是导致QPixmap错误的原因.如果您在X11上运行此代码,则QPixmap由X Pixmap资源支持,该资源受各种因素(软件和硬件)的限制.即使从您的代码中没有明显的泄漏,也可能是反复分配大的像素图会缓慢地碎片化X管理的内存池,直到无法为缩放后的像素图分配足够大的块,然后触发错误.或者它可能是图形堆栈中某处的驱动程序错误.您是否尝试过更改缩放后的大小在开始突破之前增加还是减少了限制?如果是这样,切换到QImage可能有助于减轻X上的压力.

That said, I don't think that's what causes your QPixmap error. If you're running this code on X11, then QPixmap is backed by an X Pixmap resource, which is limited by various factors (software and hardware). Even though from your code there's no obvious leak, it could be that repeatedly allocating large pixmaps slowly fragments the memory pool managed by X, up to the point where it can't allocate a block large enough for the scaled pixmap and then triggers the error. Or it could be a driver bug somewhere in the graphics stack. Have you tried if changing the scaled size increases or decreases the limit before it starts breaking? If so, switching to QImage might help relieving the pressure on X.

除此之外,代码还可以使用一些清理方法,尤其是多余的QEventLoop用法.我猜想这是一种方法,可以防止多次单击按钮直到加载新图像,但是我宁愿在下载图像时使用button.setEnabled(false)来实现此功能,因为嵌套事件循环结合在一起了网络事件是解决无数可重入问题且难以调试崩溃/错误的秘诀.

Aside from that, the code could use some cleanup, especially that superfluous QEventLoop usage. I'm guessing it's a way to prevent the button from being clicked several times until the new image has been loaded, but I'd much rather implement this using button.setEnabled(false) while the image is downloading, because nested event loops combined with network events is a recipe for countless reentrancy issues and hard to debug crashes/bugs.

我也很困惑为什么在堆上分配了size,尤其是在之后立即将其删除时,这些if (size)确实令人困惑,因为它们可以理解为if (size->isValid()),而它们的真正含义是if (size != nullptr),几乎可以保证,因为在那条线上获得OOM的机会极低. (如果您最终确实用完了内存,我想可能是在上面的readAll()或loadFromData()调用中发生的.)

I'm also confused about why size is allocated on the heap , especially when it's deleted right after, and these if (size) are really confusing, as they can be understood as if (size->isValid()) while what they really mean is if (size != nullptr), which is pretty much guaranteed as the chance of getting an OOM on that line is infinitesimally low. (if you did eventually run out of memory, my guess is it would likely happen in the readAll() or loadFromData() calls above).

ps:祝您好运再按一次该按钮500次,以检查是否对修复泄漏有所帮助;)

ps: good luck pressing that button another 500 times to check if fixing the leak helped ;)

这篇关于调用函数500次后,获取Pixmap是一个空的pixmap.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆