2014-02-27 282 views
2

我正在使用QT和QCamera對象在對話框中顯示來自相機的視頻源。我的代碼如下;刪除QCamera崩潰程序

cameratestdialog.ui

<?xml version="1.0" encoding="UTF-8"?> 
<ui version="4.0"> 
<class>CameraTestDialog</class> 
<widget class="QDialog" name="CameraTestDialog"> 
    <property name="geometry"> 
    <rect> 
    <x>0</x> 
    <y>0</y> 
    <width>400</width> 
    <height>300</height> 
    </rect> 
    </property> 
    <property name="windowTitle"> 
    <string>Dialog</string> 
    </property> 
    <widget class="QCameraViewfinder" name="viewfinder" native="true"> 
    <property name="geometry"> 
    <rect> 
    <x>40</x> 
    <y>40</y> 
    <width>281</width> 
    <height>201</height> 
    </rect> 
    </property> 
    </widget> 
</widget> 
<customwidgets> 
    <customwidget> 
    <class>QCameraViewfinder</class> 
    <extends>QWidget</extends> 
    <header>qcameraviewfinder.h</header> 
    <container>1</container> 
    </customwidget> 
</customwidgets> 
<resources/> 
<connections/> 
</ui> 

cameratestdialog.h

#ifndef CAMERATESTDIALOG_H 
#define CAMERATESTDIALOG_H 

#include <QDialog> 
#include <QCamera> 

namespace Ui { 
class CameraTestDialog; 
} 

class CameraTestDialog : public QDialog 
{ 
    Q_OBJECT 

public: 
    explicit CameraTestDialog(QWidget *parent = 0); 
    ~CameraTestDialog(); 

private: 
    Ui::CameraTestDialog *ui; 

    QCamera *camera; 
}; 



#endif // CAMERATESTDIALOG_H 

cameratestdialog.cpp

#include "cameratestdialog.h" 
#include "ui_cameratestdialog.h" 

#include <QCameraViewfinder> 
#include <QDebug> 

CameraTestDialog::CameraTestDialog(QWidget *parent) : 
    QDialog(parent), 
    ui(new Ui::CameraTestDialog), 
    camera(0) 
{ 
    ui->setupUi(this); 
    this->setAttribute(Qt::WA_DeleteOnClose); 

    delete camera; 

    camera = new QCamera; 
    camera->setViewfinder(ui->viewfinder); 
    camera->start(); 
} 

CameraTestDialog::~CameraTestDialog() 
{ 
    qDebug() << "Stopping Camera"; 
    camera->stop(); 
    camera->unload(); 
    //delete camera; 
    delete ui; 
} 

cameratestdialog.cpp的析構函數中,您可以看到我已註釋掉刪除相機的行。當我像這樣運行程序時,它工作正常(我試過釋放和調試模式),我可以根據需要多次顯示和關閉對話框而不會崩潰。當我取消註釋此行時,程序在調用析構函數時意外崩潰。

我啓動與

CameraTestDialog *dlg = new CameraTestDialog(); 
dlg->show(); 

我很高興地離開delete camera行註釋,這樣我的程序運行對話框,但並不意味着每次關閉對話框時,我的內存泄漏?什麼是停止和刪除QCamera對象的正確方法?

我正在使用QT Creator 2.8.1在2012年時代的Mac Book Air下運行Mavericks。


編輯:

我沒有安裝調試器,所以我沒有獲得在這一點上關於崩潰性質的任何詳細信息。

我懷疑camera->stop()camera->unload()調用的行爲是異步的,因此相機在實際停止之前被刪除。爲了測試這一點,我添加了while循環來檢查相機的狀態,並阻止,直到確認相機停止並卸載。我發現這些函數實際上是同步的,並且仍然具有相同的症狀(在調用delete之後的一段時間內會崩潰)。


編輯2:

我試圖改變到照相機的參考堆疊爲主,而不是基於new,併除去刪除線。完成此操作後,在顯示對話框之前,程序會在構造函數中崩潰。


編輯3:

我剛剛確認這程序不崩潰,我在Windows 7上,所以我假設式Qcamera的QT實現這個低級別的錯誤在OSX電腦上。我會盡量在QT項目中提出一個錯誤。

+0

嘗試調用'刪除相機;'呼叫後'刪除UI;'。 –

+0

感謝您的建議,只是試了一下,它有相同的症狀(在析構過程中崩潰)。我也嘗試將delete行改爲'camera-> deleteLater()'並得到相同的結果。 – aaronsnoswell

+0

我不太確定這裏發生了什麼,但是你可以試試'camera = new QCamera(this)'。這會使相機成爲對話課程的孩子。刪除對話框時應該自動刪除它。 –

回答

1

奇怪的是,我剛剛確定這確實是OSX上的某種異步問題。當我刪除相機對象之前,允許對話框處理至少19ms的事件時,程序不會崩潰。這表明,OSX QCamera實施需要一段時間才能完全關閉/斷開硬件。

CameraTestDialog::~CameraTestDialog() 
{ 
    qDebug() << "Stopping Camera"; 
    camera->stop(); 
    camera->unload(); 

    QTime dieTime = QTime::currentTime().addMSecs(19); 
    while(QTime::currentTime() < dieTime) { 
     QCoreApplication::processEvents(QEventLoop::AllEvents, 100); 
    } 

    delete camera; 

    delete ui; 
} 

請注意,在此等待期間,對話框需要處理事件,只需將一些文本打印到屏幕上即可使其仍然崩潰。此外,小於19ms會導致它仍然崩潰。

顯然,這是一個黑客攻擊的解決方案,所以我要提交bug到我已提交QTBUG-37109到Qt工程的QT項目

0

的問題是,似乎式Qcamera在一個線程中運行。刪除「太早」會導致Windows上出現QMutuex錯誤。因此,解決的辦法是camera->stop();代替camera->unload();

最後也是最重要的:與其delete camera使用

camera->deleteLater();