繁体   English   中英

C++ std::thread 终止调用而没有活动异常已中止

[英]C++ std::thread terminate called without an active exception Aborted

我这里有一个代码,它从在单独线程中运行视频捕获操作的相机捕获视频 stream。 代码可以编译,但是当我尝试运行它时,我收到以下错误。

我做了一些研究,发现这个问题与缺少th.join();相关。 但是当用户通过按q键中断该过程时,我已经这样做了。 在那之前,代码应该继续在创建的线程中运行。 所以这告诉我应该在其他地方加入线程。

如果我通过替换thread th(&VideoCaptureAsync::update, this); 使用VideoCaptureAsync::update(); 并删除th.join(); ,错误消失了,但这显然违背了这段代码的目的。

Output

内部启动 function

(进程:10748):GStreamer-CRITICAL **:gst_element_get_state:断言“GST_IS_ELEMENT(元素)”失败

内部启动 function

内部更新 function

在没有活动异常的情况下调用终止

内读 function

中止(核心转储)

代码

/*
* Asynchronous_video_capture.cpp
*
* Copyright (C) 2019 C. S. G.
*
* MIT License
*/

#include <iostream> // for standard I/O
#include <string>   // for strings
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>     // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp>  // Video write
#include <opencv2/opencv.hpp>
#include <opencv2/core/utility.hpp>
#include <thread>
#include <tuple>

using namespace cv;
using namespace std;

void foo(bool &keep_run){
    cout << "Inside the thread: Interrupt flag = " << keep_run << endl;
    if (std::cin.get() == 'q') {
        keep_run = false;
        cout << "User Interrupted the process. Interrupt flag = " << keep_run << endl;
    }
}

class VideoCaptureAsync
{
private:
    VideoCapture cam;
    thread th;
    bool read_lock;
    Mat frame;
    Mat grabbed;
    bool isStarted;
public:
    void initiate(unsigned int camId, unsigned int width, unsigned int height, double fps);
    void start();       // a start function to create and start the thread
    void update();      // an update function that will be called asynchronously
    tuple<Mat, Mat> read();        // a read function that we will call from our code to retrieve a new frame.
    void stop();        // a stop function to stop (join) the thread
    void exit();        // an __exit__ function to clean up some resources.
};

void VideoCaptureAsync::initiate(unsigned int camId, unsigned int width, unsigned int height, double fps){
    cout << "Inside initiate function" << endl;
    cam.open(camId);
    if (!cam.isOpened())
    {
        cerr  << "Could not open the VideoCapture camera: " << camId << endl;
    }
    cam.set(CV_CAP_PROP_FRAME_WIDTH, width);
    cam.set(CV_CAP_PROP_FRAME_HEIGHT, height);
    cam.set(CAP_PROP_FPS, fps);

    isStarted = false;
    read_lock = false;
    VideoCaptureAsync::start();
}

void VideoCaptureAsync::start(){
    cout << "Inside start function" << endl;
    if (isStarted) {
        cout << "Asynchroneous video capturing has already been started" << endl;
    }
    isStarted = true; 
    thread th(&VideoCaptureAsync::update, this);
    //VideoCaptureAsync::update();
}

void VideoCaptureAsync::update(){
    cout << "Inside update function" << endl;
    while(isStarted){
        Mat frame_update;
        Mat grabbed_update;
        tie(frame_update, grabbed_update) = VideoCaptureAsync::read();
        if(!read_lock){
            frame_update.copyTo(frame);
            grabbed_update.copyTo(grabbed);
        }
    }
}

tuple<Mat, Mat> VideoCaptureAsync::read(){
    cout << "Inside read function" << endl;
    if (!read_lock){
        read_lock = true;
        Mat frame_read;
        cam.read(frame_read);
        Mat grabbed_read;
        read_lock = false;
        return make_tuple(frame_read, grabbed_read);
    }
}

void VideoCaptureAsync::stop(){
    cout << "Inside stop function" << endl;
    th.join();
    isStarted = false;
    read_lock = true;
}

void VideoCaptureAsync::exit(){
    cout << "Finished writing ..." << endl;
    cam.release();
}

int main(int argc, char *argv[]){

    const unsigned int camId = 1;
    const bool enableOutput = true;
    const unsigned int w = 1280;
    const unsigned int h = 720;
    double fps = 30.0;


    VideoCaptureAsync obj;
    obj.initiate(camId,w,h,fps);
    bool keep_running = true;
    thread th1(foo, std::ref(keep_running));
    Mat original_frame;

    while (keep_running) {
        std::tie(std::ignore, original_frame) = obj.read();

        if (enableOutput) {
            imshow("Retrieved Image", original_frame);
            waitKey(1000/fps);
        }
    }

    obj.stop();
    obj.exit();

}

在您的start () 方法中:

thread th(&VideoCaptureAsync::update, this);

该语句在名为thstart()方法中创建了一个新的本地 object,一个全新的、刚下线的std::thread object,并以创建新执行线程的方式构造它。

紧接着, start()返回。 这会破坏这个本地 object,调用它的析构函数,并导致您的异常。

您的明显意图是使用th成员来创建新的执行线程,而不是在start()方法中创建新的本地 object 。 但是上面的 C++ 语法是一个声明。 It declares a new object, and when used in side a function it creates a new local object (in automatic scope), that gets automatically destroyed at the end of the scope. 这就是 C++ 的工作原理。

为了让新的执行线程从您现有的 class 成员开始:

th=thread{&VideoCaptureAsync::update, this};

(使用现代 C++ 的统一初始化语法)。 有关详细信息,请参阅“ C++11 中的线程延迟启动”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM