调用.hpp中定义的类报错:VS2019+OpenCV3.4.1出现this->p空指针访问冲突
报错触发原因
- 成员变量初始化顺序不符合C语法规则:C类中成员变量的初始化顺序严格遵循声明顺序,而非赋值顺序。你代码中
imgBlank、height、width的声明位置早于original,实例化类时会先初始化imgBlank,此时original还未完成初始化,是无数据的空cv::Mat对象,调用original.size()时访问了空指针,直接触发mat.inl.hpp中的内存访问异常。 - 类内初始化调用成员函数逻辑非法:成员变量
imgGUI在类内直接初始化时调用了crosshair()、imgCoordinate()两个成员函数,此时类实例还未完成整体构造,posX、posY等依赖变量均未赋值,逻辑不成立,属于潜在崩溃点。 - 额外隐患:
cv::Mat默认是浅拷贝,原代码中Mat img = imgBlank直接赋值后绘制,会修改原始的imgBlank对象,导致后续生成的GUI图像叠加旧的绘制内容。
修复方案
- 调整成员变量声明顺序,将作为依赖的
original放在类成员的最前方。 - 取消依赖
original的变量的类内默认初始化,新增独立的参数更新方法,在original赋值后手动调用完成初始化,同时增加非空判断避免空指针。 - 将预初始化的
imgGUI改为动态生成的成员函数,需要使用时实时计算返回结果,避免类未构造完成就调用成员函数的问题。 - 绘制图像时调用
clone()做深拷贝,避免修改原始的空白背景图。
修复后完整代码
#pragma once #include "Header_1.h" class GUI_1 { public: // 输入源图像,作为依赖放在最前面声明 cv::Mat original; // 目标跟踪坐标变量 int posX = 0; int posY = 0; // 十字准星、文本颜色参数 double red = 0; double green = 255; double blue = 255; /// @brief 更新GUI依赖参数,original赋值后、坐标变更后可调用 void updateParams() { if (original.empty()) { CV_Error(cv::Error::StsBadArg, "输入的original图像为空"); } height = original.size().height; width = original.size().width; imgBlank = cv::Mat::zeros(original.size(), CV_8UC3); } /// @brief 绘制十字准星 cv::Mat crosshair() { cv::Mat img = imgBlank.clone(); // 深拷贝避免修改原始背景 int length = 10; line(img, cv::Point(posX - length, posY), cv::Point(posX + length, posY), cv::Scalar(blue, green, red), 1); line(img, cv::Point(posX, posY - length), cv::Point(posX, posY + length), cv::Scalar(blue, green, red), 1); return img; } /// @brief 绘制坐标文本 cv::Mat imgCoordinate() { cv::Mat img = imgBlank.clone(); const int subX = 2; const int subY = 2; std::string Text = "X=" + std::to_string(posX) + " Y=" + std::to_string(posY); putText(img, Text, cv::Point(posX + subX, posY + subY), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(blue, green, red), 1); return img; } /// @brief 生成输出GUI图像 cv::Mat getImgGUI() { if (imgBlank.empty()) { updateParams(); } return imgBlank + crosshair() + imgCoordinate(); } private: // 黑色背景图像 cv::Mat imgBlank; // 图像尺寸参数 int height = 0; int width = 0; };
使用示例
// 实例化类 GUI_1 gui; // 给输入源图像赋值 gui.original = imread("test.jpg"); // 更新参数 gui.updateParams(); // 赋值坐标 gui.posX = 100; gui.posY = 100; // 获取生成的GUI图像 Mat guiImg = gui.getImgGUI(); imshow("GUI", guiImg);
内容的提问来源于stack exchange,提问作者Grey Cat
相关产品推荐
相关产品推荐

