删除QCamera崩溃程序

时间:2014-02-27 00:07:55

标签: c++ macos qt camera crash

我正在使用QT和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上运行。


修改

我没有安装调试器,因此我目前没有关于崩溃性质的更多信息。

我怀疑camera->stop()camera->unload()调用的行为是异步的,因此相机在实际停止之前就被删除了。为了测试这个,我添加了while循环来检查摄像机的状态,并阻止直到确认摄像机被停止并卸载。我发现这些函数实际上是同步的,并且仍然具有相同的症状(在调用delete之后的一段时间内崩溃)。


编辑2:

我尝试将对摄像机的引用更改为基于堆栈而不是基于new,并删除了删除行。执行此操作后,程序在构造函数中崩溃,然后才显示对话框。


编辑3:

我刚刚确认这个程序在Windows 7上没有崩溃,所以我认为这是OSX计算机上QCamera的QT实现中的一个低级错误。我将尝试提出QT项目的错误。

2 个答案:

答案 0 :(得分: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;
}

请注意,对话框需要在此等待期间处理事件,只需将一些文本打印到屏幕使其仍然崩溃。此外,任何小于19毫秒都会导致它仍然崩溃。

显然这是一个黑客解决方案,所以我要向QT项目提交一个错误我已经向Qt项目提交了QTBUG-37109

答案 1 :(得分:0)

问题是QCamera似乎在Thread中运行。 “太早”删除它会导致Windows上出现QMutuex错误。因此,解决方案是camera->stop();而不是camera->unload();

最后也是最重要的:而不是delete camera使用

camera->deleteLater();