2014-02-27 228 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();