OpenCV C++循环创建VideoCapture报corrupted double-linked list错误
问题说明
实现多摄像头FPS采集程序时,第二次创建VideoCapture实例会触发内存错误崩溃,相关表现如下:
- 首次打开摄像头读FPS正常,输出
Frames: 30后第二次执行到VideoCapture video(url)时直接报错corrupted double-linked list后coredump - 尝试加打开间隔延时、校验摄像头配置map均无法解决问题
- 注释部分打印语句后程序可短暂运行,运行一段时间后仍会崩溃
- gdb回溯显示崩溃点位于FFmpeg库的内存分配流程,最终由glibc检测到双链表损坏触发abort
附核心问题代码:
// 主函数循环逻辑 while(true) { for(it_cam = camerasIp.begin(); it_cam != camerasIp.end(); ++it_cam) { GetCamFps(it_cam->second); } cout << "" << endl; } // 单次获取FPS逻辑 void GetCamFps(string url) { VideoCapture video(url); double fps = video.get(CAP_PROP_FPS); cout <<"Frames: " << fps << endl; video.release(); }
根因分析
- 核心问题是OpenCV 4.2版本的FFmpeg后端存在已知的资源释放缺陷:当前实现在无限循环中反复创建、销毁
VideoCapture实例,每次都会触发FFmpeg的流上下文初始化、销毁流程,旧版本的封装逻辑存在内存越界写问题,会破坏glibc malloc管理空闲内存块的双链表元数据,最终触发corrupted double-linked list报错。注释打印语句后崩溃延后只是因为内存布局变化,问题本身没有消失。 - 刚打开RTSP流时FFmpeg还未完成元数据解析,此时直接读取
CAP_PROP_FPS属性会访问未初始化的内部状态,进一步加剧内存异常。 - 函数中手动调用
video.release()是多余操作:局部VideoCapture变量在函数退出时会自动执行析构释放资源,手动调用后析构阶段会触发重复释放,放大内存损坏概率。 - 加sleep延时无法解决问题:内存损坏是库本身的逻辑bug导致的,和打开间隔时长无关。
解决方案
按优先级从高到低可选择以下方案:
- 优先方案:避免反复创建销毁
VideoCapture实例,程序启动时一次性初始化所有摄像头的捕获对象,常驻内存复用,循环中直接读取已打开实例的FPS属性,从根源上规避反复初始化/释放带来的内存问题。参考实现如下:
int main(int argc, char* argv[]) { map<string, string> camerasIp; LoadConfig(&camerasIp); // 启动时一次性打开所有摄像头 map<string, VideoCapture> camCaptures; for(auto &cam_entry : camerasIp) { camCaptures[cam_entry.first].open(cam_entry.second, CAP_FFMPEG); // 打开失败直接打日志标记 if(!camCaptures[cam_entry.first].isOpened()) { cerr << "摄像头打开失败: " << cam_entry.first << endl; } } while(true) { for(auto &cap_entry : camCaptures) { if(!cap_entry.second.isOpened()) continue; // 可选:读1-2帧空帧,确保元数据解析完成 Mat temp; cap_entry.second >> temp; double fps = cap_entry.second.get(CAP_PROP_FPS); cout << "摄像头" << cap_entry.first << " FPS: " << fps << endl; } // 加1秒间隔降低CPU占用 this_thread::sleep_for(chrono::seconds(1)); } // 程序退出时对象会自动析构释放资源,无需手动调用release return 0; }
- 若必须临时打开流获取数据:将OpenCV升级到4.5及以上版本,对应FFmpeg库同步升级到4.0以上版本,新版本修复了大量FFmpeg后端的内存越界、重复释放问题;打开流时显式指定
CAP_FFMPEG后端,避免自动探测后端带来的异常。 - RTSP流场景可额外配置传输协议为TCP,降低流解析失败概率:可通过设置环境变量
OPENCV_FFMPEG_CAPTURE_OPTIONS="rtsp_transport;tcp"实现,也可直接在RTSP URL后拼接参数。
内容的提问来源于stack exchange,提问作者Francisco Madueño Chulian
相关产品推荐
相关产品推荐

