You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu下C++ OpenCV实时图像处理集成UART中断出现Core Dumped问题

问题根因
  • 你将VideoCapture vid定义为全局变量,它的初始化在main函数执行前就完成,此时Linux下V4L2设备驱动上下文、OpenCV用户态运行环境还未完全就绪,本身就存在稳定性隐患,结合异步信号中断更容易触发内存访问错误。
  • SIGIO信号是异步触发的,可能在执行vid.set、vid.read的任意阶段打断代码运行,而OpenCV的VideoCapture类成员函数没有做异步信号安全的保证,信号打断后恢复执行时,VideoCapture内部状态已经被破坏,因此触发段错误。你删除分辨率配置代码后程序正常运行,是因为vid.set属于耗时较长的IO操作,被SIGIO信号打断的概率远高于帧读取操作,只是避开了问题触发场景,并没有从根源解决问题。
  • 你尝试把vid.set两行放到全局作用域会报错,是因为全局作用域只能声明变量、定义函数,不能直接执行普通的成员函数调用语句,编译器会把这行当成类型定义解析,自然报vid does not name a type错误。
解决方案
  1. 将全局的VideoCapture定义移到main函数内部,避免全局对象初始化的不稳定问题,所有VideoCapture的操作都放在main函数的可控流程中执行。
  2. 信号处理函数仅做信号到达标记,不要执行任何非异步信号安全的操作(比如printf、read等),所有UART数据读取逻辑移到主循环轮询处理,避免信号打断OpenCV的执行流程。
  3. 给sigaction添加SA_RESTART标志,让被信号打断的系统调用自动重启,避免OpenCV内部的V4L2调用被打断后返回错误导致状态异常。
  4. vid.set的调用放在vid.isOpened()判断之后、UART配置完成之前,确保VideoCapture初始化完成后第一时间设置参数,避免后续信号打断参数配置流程。

修改后的核心代码参考:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <errno.h>
#include <termios.h>
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

// 异步信号安全的全局标记位,仅用于标记UART信号到达
volatile sig_atomic_t uart_received = 0;
void signal_handler_IO(int status);  

int main(int argc, char *argv[])
{
    // VideoCapture移到main内部定义
    VideoCapture vid("/dev/video0", CAP_V4L2);
    int fd;
    struct termios termAttr;
    struct sigaction saio;
    const int fps = 20;
    Mat frame;

    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1)
    {
        perror("open_port: Unable to open /dev/ttyUSB0\n");
        exit(1);
    }

    saio.sa_handler = signal_handler_IO; 
    // 添加SA_RESTART标志,自动重启被信号打断的系统调用
    saio.sa_flags = SA_RESTART; 
    saio.sa_restorer = NULL;
    sigaction(SIGIO,&saio,NULL); 
    fcntl(fd, F_SETFL, FNDELAY|FASYNC);
    fcntl(fd, F_SETOWN, getpid());
    tcgetattr(fd,&termAttr);
    cfsetispeed(&termAttr,B9600);
    cfsetospeed(&termAttr,B9600);
    termAttr.c_cflag &= ~PARENB;
    termAttr.c_cflag &= ~CSTOPB;
    termAttr.c_cflag &= ~CSIZE;
    termAttr.c_cflag |= CS8;
    termAttr.c_cflag |= (CLOCAL | CREAD); 
    termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
    termAttr.c_iflag &= ~(IXON | IXOFF | IXANY);
    termAttr.c_oflag &= ~OPOST;
    tcsetattr(fd, TCSANOW, &termAttr);

    printf("UART1 configured....\n");

    if (!vid.isOpened())
    {
        return -1;
    }
    // 进入主循环前先完成分辨率配置,此时不会被UART信号打断
    vid.set(CAP_PROP_FRAME_WIDTH, 1280);
    vid.set(CAP_PROP_FRAME_HEIGHT, 720);

    while (vid.read(frame))
    {
        imshow("webcam", frame);

        // 轮询UART事件,处理数据
        if (uart_received) {
            char buf[256] = {0};
            int len = read(fd, buf, sizeof(buf)-1);
            if (len > 0) {
                printf("received UART data: %.*s\n", len, buf);
                // 此处添加你的UART数据处理逻辑
            }
            uart_received = 0;
        }

        if (waitKey(1000/fps) >= 0)
          break;
    }   
    
    destroyAllWindows();
    vid.release();
    close(fd);
    exit(0);             
}

void signal_handler_IO (int status)
{ 
    // 仅修改标记位,不做其他操作
    uart_received = 1;
}  

内容的提问来源于stack exchange,提问作者ayashlokumu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 09:45:03