尝试将Gst Buffer内存复制到Torch Tensor时出现段错误
问题分析与解决方案
核心问题定位
段错误的根源大概率是OpenCV Mat构造时未考虑GStreamer Buffer的内存对齐/步长,导致Mat访问了非法内存区域,后续Torch Tensor的clone操作触发内存访问错误。此外代码中还有提前读取未初始化变量的问题,会干扰调试。
具体问题点
- 提前读取未初始化的
map变量:在gst_buffer_map前就打印map.size,此时map是未初始化的垃圾值,完全无意义。 - OpenCV Mat构造忽略GStreamer的内存步长:GStreamer的Buffer为了内存对齐,每行数据会有额外的padding字节(即
map.stride不等于width*channels),直接用默认步长构造Mat会导致后续内存越界访问,虽然OpenCV的imwrite能正常执行,但内存已被破坏,触发后续Torch操作的段错误。 - 硬编码尺寸风险:代码中固定写死1920x2560,若GStreamer管道实际输出的尺寸不符,会直接导致内存访问错误。
修复代码
static GstPadProbeReturn on_probe( GstPad *pad, GstPadProbeInfo *info, gpointer user_data ) { GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); if (!buffer) return GST_PAD_PROBE_OK; GstMapInfo map; FrameInfo *fr = static_cast<FrameInfo*>(user_data); std::ostringstream file_name; file_name << "image"; // 先获取并验证当前Pad的实际Caps,避免硬编码错误 gint width = 0, height = 0; const gchar *format = nullptr; GstCaps *caps = gst_pad_get_current_caps(pad); if (caps) { GstStructure *s = gst_caps_get_structure(caps, 0); gst_structure_get_int(s, "width", &width); gst_structure_get_int(s, "height", &height); format = gst_structure_get_string(s, "format"); gst_caps_unref(caps); } // 验证格式和尺寸是否符合预期 if (width != 2560 || height != 1920 || g_strcmp0(format, "RGB") != 0) { std::cerr << "Unexpected caps: " << width << "x" << height << ", format=" << format << std::endl; return GST_PAD_PROBE_OK; } if (gst_buffer_map(buffer, &map, GST_MAP_READ)) { // 现在打印有效map信息 std::cout << "Buffer size: " << map.size << ", stride: " << map.stride << std::endl; // 关键修复:传入GStreamer的实际步长给OpenCV Mat cv::Mat frame(height, width, CV_8UC3, map.data, map.stride); cv::cvtColor(frame, frame, cv::COLOR_RGB2BGR); cv::Mat norm_frame; frame.convertTo(norm_frame, CV_32FC3, 1.0f / 255.0f); file_name << fr->frame_no << ".png"; bool success = cv::imwrite(file_name.str(), frame); if (!success) { std::cerr << "Failed to write image"; } // 构造Tensor并clone(此时norm_frame内存是安全的) at::Tensor tensor = torch::from_blob( norm_frame.data, {1, norm_frame.rows, norm_frame.cols, 3}, at::kFloat ).clone(); tensor = tensor.permute({0, 3, 1, 2}); // 执行模型推理 torch::jit::IValue output = fr->model.forward({tensor}); fr->frame_no++; gst_buffer_unmap(buffer, &map); } GstClockTime pts = GST_BUFFER_PTS(buffer); std::cout << "Buffer PTS: " << GST_TIME_AS_MSECONDS(pts) << " ms" << std::endl; return GST_PAD_PROBE_OK; }
额外建议
- 若模型运行在GPU上,需确保Tensor正确移动到GPU:
tensor = tensor.to(at::kCUDA);,同时确认模型已加载到GPU。 - 检查
FrameInfo中的model是否正确初始化(TorchScript模型是否成功加载,无空指针)。 - 若段错误仍存在,可使用
gdb或valgrind定位具体的内存访问错误点,确认是Torch侧还是OpenCV侧的问题。
内容的提问来源于stack exchange,提问作者vizn
相关产品推荐
相关产品推荐

