2016-12-22 8 views
0

イメージをqtラベルで表示しています。以下は私のコードですPixmapを取得すると、関数を呼び出す際のnull pixmapです。

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回を超えないならそれはうまくいきます。最初にそれを超えるとこのエラーが表示されました

QPixmap::scaled: Pixmap is a null pixmap 

イメージを表示していません。その後、誰かが画像の要求を再度送信すると、次のエラーが表示されます。 Qtがイベントハンドラからスローされた例外を検出しました。イベントハンドラからの例外を投げることは、Qtではサポートされていません。 を再度実装してQApplication::notify()を実装し、そこにすべての例外をキャッチする必要があります。

上記のコードでエラーが発生していません。誰かが私にこれを解決する方法を教えてもらえますか?

答えて

0

明白なリークはqnam_push_button_clicked_show_image = new QNetworkAccessManager(this);です。どこでもバランスのとれた削除はありません。通常、QNAMは一度作成してから、1回の要求で作成するのではなく、アプリケーションの存続期間中に再利用する必要があります。だからクラスメンバー(uiと同じ)のqnam_push_button_clicked_show_imageを回すことで、漏れを修正してコードの効率を改善します。

しかし、私はあなたのQPixmapエラーの原因とは思わないと言いました。このコードをX11で実行している場合、QPixmapはさまざまな要因(ソフトウェアとハ​​ードウェア)によって制限されるX Pixmapリソースによってバックアップされます。あなたのコードから明白なリークはありませんが、大きなピクスマップを繰り返し割り当てると、Xで管理されているメモリプールが、スケーリングされたピクスマップに十分な大きさのブロックを割り当てられないようにゆっくりと断片化し、 。あるいは、グラフィックススタックのどこかにドライバのバグかもしれません。スケーリングされたサイズを変更すると、ブレークを開始する前に制限を増減すると試しましたか?その場合、QImageに切り替えると、Xへの負担を軽減するのに役立ちます。

これ以外にも、コードでは、特に余計なQEventLoopの使用を防ぐことができます。私は、新しいイメージがロードされるまで、ボタンが数回クリックされないようにする方法だと思っていますが、入れ子のイベントループを組み合わせたので、イメージのダウンロード中にbutton.setEnabled(false)ネットワークイベントは、無数のリエントラント問題のレシピであり、クラッシュ/バグのデバッグは困難です。

私もsizeはそれが適切後に削除されます場合は特に、ヒープ上に割り当てられ、そして彼らが本当に意味することはかなりある、if (size != nullptr)ている間、彼らはif (size->isValid())として理解することができるように、これらif (size)は、本当に混乱しているされている理由について困惑していますその行でOOMを取得する可能性が非常に低いことは非常に低いです。 (最終的にメモリ不足になった場合は、上記のreadAll()またはloadFromData()の呼び出しで発生する可能性があります)。

PS:;ああ

+0

)とあなたが ''場合は 'onPushButtonClickedRequestCompleted(QNetworkReply *返信)から早期帰国しているときに別のマイナーリークがあります幸運リークを修正かどうかをチェックするために、そのボタンに別の500回を押すと助けましたreply'にエラーがあります。あなたは 'reply-> deleteLater();'を呼ばないことでリークしています。通常、このようなスロットでは最初に呼び出されますが、スロットが終了するまで返信が実際に削除されないので安全です。最後に呼び出す必要はありません。 –

関連する問題