一个 将一个无效参数传递给了将无效参数视为严重错误的函数 及写入位置时发生访问冲突的问题的解决
我的应用大体功能是这样的,使用opencv的接口,从摄像头实时读取color数据显示,并完全保存所有视频到硬盘,已经点击按钮之后将当前的数据帧保存为图片存储到硬盘。
第一个错误:
第二个错误:
void FaceCapture::showColor(cv::Mat colorFrame)
{
//colorframeMutex.lock();
m_colorFrame = colorFrame;
if (g_colorWriter.isOpened())
{
g_colorWriter << colorFrame;
}
//colorframeMutex.unlock();
//cv::resize(colorFrame, frameForShow, dsize );
int img_width = colorFrame.cols; // 在这行发生如上错误,上面两个错误都有可能发生。
int img_height = colorFrame.rows;
int channelnum = colorFrame.channels();
if (NULL == g_prgbdatabuff)
{
g_prgbdatabuff = (uchar *)malloc(img_width * img_height * channelnum);
}
uchar* colorData = colorFrame.data;
bool isColorImgTwoDark = true;
int MaxValueCount = 0;
for (int i = 0; i < img_width * img_height; i++)
{
int rgbaOffset = i * channelnum;
g_prgbdatabuff[rgbaOffset] = colorData[rgbaOffset + 2];
g_prgbdatabuff[rgbaOffset + 1] = colorData[rgbaOffset +1];
g_prgbdatabuff[rgbaOffset + 2] = colorData[rgbaOffset];
if ((255 == colorData[rgbaOffset + 2])
&& (255 == colorData[rgbaOffset + 1])
&& (255 == colorData[rgbaOffset]))
{
MaxValueCount++;
isColorImgTwoDark = false;
}
if ((IMG_DARKNESS_THRESHOLD <= colorData[rgbaOffset + 2])
|| (IMG_DARKNESS_THRESHOLD <= colorData[rgbaOffset + 1])
|| (IMG_DARKNESS_THRESHOLD <= colorData[rgbaOffset]))
{
isColorImgTwoDark = false;
}
}
QImage img(g_prgbdatabuff, img_width, img_height, QImage::Format_RGB888);
QPixmap pixmap = QPixmap::fromImage(img);
QPixmap scaredPixmap = pixmap.scaled(ui.label_color->width(), ui.label_color->height());
ui.label_color->setPixmap(scaredPixmap);
if (IMG_COLOR_OVER_EXPOSURE_PIXEL_COUNT <= MaxValueCount)
{
//ui.label_color_quality->setStyleSheet("color: rgb(255,0,0);");
ui.label_color_quality->setText(QString::fromLocal8Bit("Color图像过度曝光"));
}
else if (true == isColorImgTwoDark)
{
//ui.label_color_quality->setStyleSheet("color: rgb(255,0,0);");
ui.label_color_quality->setText(QString::fromLocal8Bit("Color图像过暗"));
}
else
{
//ui.label_color_quality->setStyleSheet("color: rgb(0,0,0);");
ui.label_color_quality->setText(QString::fromLocal8Bit("Color图像正常"));
}
//free(data);
}
遇到这个问题,非常头大,网上的说法也乱七八糟。基本找不到一个可行的解决方案。而且这个问题也不是每一个数据帧都出现,不断的测试,突然什么时候就崩出来。
针对这个问题,第一反应是colorFrame 的Mat结构被破坏了。然后开始找各种关于Mat的信息。首先寻找判断判断Mat是否有效的两个函数:empty(如果Mat的data区域没有数据,或者尚未开辟空间,则返回false。),另一个是continuous(用来判断Mat中的数据是否是连续内存存的);加入如上两个判断之后发现虽然Mat比较大,1280*800的分辨率存储color数据,但是这两个判断基本上也都能通过,最后了解到像Mat结构确实比较特殊,Mat的赋值运算= 不会开辟新的空间,只会增加引用计数,于是找到可以使用clone或者copyto来进行深copy,多次尝试之后依然无法解决问题。另外了解到Mat 作为参数时,及时是直接传值其实也是传指针。搞过来搞过去,还是无法解决问题。
调用上面showColor函数的调用函数是如下的线程函数:
void ColorThread(VideoCapture cap)
{
cv::Mat input_image;
Rect faceRect;
clock_t currentTime;
bool isReadOk;
while (g_running)
{
isReadOk = cap.read(input_image);
if (false == isReadOk)
{
continue;
}
if (input_image.empty())
{
continue;
}
//这里拿到彩色图之后对图像进行人脸检测,检测成功后可以根据一定的条件设置ROI曝光
detectFace(input_image, faceRect);
currentTime = clock();
if (currentTime - LastSetRoiTime > (1 * CLOCKS_PER_SEC))
{
if (faceRect.width > 50)
{
if (!CAEParamSetting::setAEROIArea(faceRect))
{
logUtil.error("WRITER BUFFER ERROR");
}
}
LastSetRoiTime = currentTime;
}
g_io_mutex.lock();
g_w->showColor(input_image);
g_io_mutex.unlock();
}
}
根据上面的函数我又猜想是不是g_io_mutex使用lock不合适,showColor发生异常导致锁无法释放,于是改用lock_guard来包装g_io_mutex。这个方法也不凑效。
于是开始使用懒人定位法,一行一行注释掉看到底是哪一行发生问题。结果把g_w->showColor(input_image);注释掉后没发生问题。于是就盯着这个函数。然后进入这个函数,再一行一行的注释看是否能发生问题。最后发现,把如下保持视频的代码注释掉之后:
if (g_colorWriter.isOpened())
{
g_colorWriter << colorFrame;
}
这个问题很难出现。于是想到是不是得给主线程中操作g_colorWriter的地方加锁,g_colorWriter在应用中也会进行多次open及release。保证互斥访问。加锁之后果然问题解决。
应用中还有一个保存m_colorFrame图片到硬盘的imwrite操作,再刚才的调试过程中是注释掉的,现在放开之后,会再imwrite保存图片的地方也出现上述问题。于是在imwrite的地方加了同一把锁g_io_mutex。在这里加锁之后,问题果然解决。
到此,其实问题的原因已经比较清楚了,这是一个多线程访问共享数据,导致访问数据冲突出现的问题。
但是遇到另外一个问题。界面上的操作变得非常卡,于是想到应该是g_io_mutex锁保护的关键区域太多导致。将不必要的操作放到锁的外面,缩小关键区域之后,界面也不卡了。问题顺利解决。
一个 将一个无效参数传递给了将无效参数视为严重错误的函数 及写入位置时发生访问冲突的问题的解决相关推荐
- findContours函数报错:“将一个无效参数传递给了将无效参数视为严重错误的函数”解决方案之一
在使用findContours函数时,release可以通过,debug一直在报错:"将一个无效参数传递给了将无效参数视为严重错误的函数". 这里有个大牛汇集的好多种解决方法: h ...
- 【C++】VS中读写操作(fclose.cpp)引发中断——将一个无效参数传递给了将无效参数视为严重错误的函数
[C++]VS中读写操作(fclose.cpp)引发中断--将一个无效参数传递给了将无效参数视为严重错误的函数 遇到的问题 跑数据测试程序时,突然跳出报错中断信息,显示触发断点,错误如下图所示. 但是 ...
- 0x0FF0ED76 (ucrtbased.dll) (Project5.exe 中)处有未经处理的异常: 将一个无效参数传递给了将无效参数视为严重错误的函数。 出现了
void drop(int a)//一个删除deque容器中元素的函数{deque<int>::iterator it;it = kn.begin();kn.erase(it+a);cou ...
- C++ 读取文件时报错“将一个无效参数传递给了将无效参数视为严重错误的函数”解决方法
** C++ 读取文件时报错"将一个无效参数传递给了将无效参数视为严重错误的函数"解决方法 最近在运行工程时需要读取stl网格文件,但是在运行时发现报错如下: 但是之前运行过一个测 ...
- findContours函数报错:“将一个无效参数传递给了将无效参数视为严重错误的函数”解决方案
先说一下出错时的环境配置:Win10+VS2015+OpenCV3.2.0 在编写火焰检测程序时候,用到findCoutours函数提取火焰边缘轮廓,以便找寻静态特征.但是在调试运行时,弹出:&quo ...
- 0x00007FFE9071C408 (ucrtbase.dll) (xxx.exe 中)处有未经处理的异常: 将一个无效参数传递给了将无效参数视为严重错误的函数。
1.调试VS程序,弹出异常:0x00007FFE9071C408 (ucrtbase.dll) (xxx.exe 中)处有未经处理的异常: 将一个无效参数传递给了将无效参数视为严重错误的函数. 2.在 ...
- 用于调用的参数太少/写入位置时发生冲突/检测到无效的异常处理程序例程
用于调用的参数太少/写入位置时发生冲突/检测到无效的异常处理程序例程 针对新人学C过程中可能遇到的一类问题 我们在学习中经常遇到这种情况: #include<stdio.h> void m ...
- VS中fseek.cpp引发断点——将一个无效参数传递给了将无效参数视为严重错误的函数
错误界面: 原因: stream无效,文件打开失败. 可能路径没写?可能没有该文件?再或者文件被占用? 可能其它因素导致文件没有被打开,stream文件流是无效的. 当你传了个无效参数去访问文件或者内 ...
- C++将一个无效参数传递给了将无效参数视为严重错误的函数
编译项目出错如下 打开调用堆栈,查看调用列表 最终定位到下面代码,文件没有写入的权限,导致无法读取文件而出错 由于没有成功写入ini文件,所以下面就无法读取ini文件
最新文章
- Android App自适应draw9patch不失真背景
- COM+在win2003+IIS+MSSQL环境下的部署步骤
- python3开发工具推荐_python开发工具有哪些?我推荐这5款python开发工具!
- 条款9:避免隐藏标准形式的new
- bootscripttable前端排序无效_前端你应该知道的八条bug分享给你们
- 如何设置工作流到了某一节点自动执行java方法_2019年JAVA最常见面试题汇总(收藏)...
- 防范网络*** 应用层防护是重点
- velodyne显示点云中grid的单位_孝感好的舞台背景显示屏施工创新服务_胜辉屏安...
- 简明 Vim 练级攻(转自coolshell)
- stringbuilder寻找字符串位置可能存在多个 java_java面试题整理(一)
- VC运行库修复安装一键安装
- Java jdk的下载与安装
- ILSVRC2012下载+训练
- Excel科学计数法转换成文本完整显示
- GC bias GC偏好
- 文字转化为二维码(数据加密)
- 焦虑症是精神病吗?缓解焦虑症的方法有哪些
- 北工大2014c语言真题及答案新课标,北京工业大学2006--2007学年《面向对象程序设计》期末考试题及答案...
- 双11_淘宝双11_天猫双11_双11是什…
- Mapbox离线字体 glyphs