opencv 库的双链接列表损坏

Corrupted double linked-list for opencv library

本文关键字:列表 损坏 链接 opencv      更新时间:2023-10-16

嗨,我写了这个简单的程序

主.cpp

std::vector<cv::Mat> PD_Classifier_VEC;
#define Folder_Address ""
int Main()
{
        int overall_counter=0;
        for(int j = 0 ; j < 600 ; j++)
          {
               QString address = Folder_Address + QString::number(overall_counter++) +".jpg";
               cv::Mat image = cv::imread(address.toUtf8().constData(),0);
               PD_Classifier_VEC.push_back(image);
               PD();
          }
}

局部放电功能

void PD()
{
            static int Total_Frame_Number=0;
            Total_Frame_Number++;
            cv::Mat Point_MAT = cv::Mat(PD_Classifier_VEC[0].size(),CV_8UC1,cv::Scalar::all(0)); 
   ....//Some Calculation //
       PD_Classifier_VEC[0].release();
       PD_Classifier_VEC.erase(PD_Classifier_VEC.begin());
}

这段代码工作正常,直到 j=56,之后 Qt 显示此错误并退出!!

*** Error in `/home/parsa/QtProjects/QtVLPR/QtVLPR': corrupted double-linked list: 0x0000000000dcf880 ***

我在调试器模式下运行代码,并将此 if 语句代码添加到 PD() 函数中:

void PD()
{
            static int Total_Frame_Number=0;
            Total_Frame_Number++;
            cv::Mat Point_MAT = cv::Mat(PD_Classifier_VEC[0].size(),CV_8UC1,cv::Scalar::all(0)); 
   ....//Some Calculation //
        if(Total_Frame_Number==56)
        {
        std::cout<<Point_MAT<<"n";            //it displays the elements perfectly
        int Nonz = cv::countNonZero(Point_MAT);  //it runs too
        cv::imshow("Point_MAT",Point_MAT);          //here the error appears !!!
        cv::waitKey();
        }
       PD_Classifier_VEC[0].release();
       PD_Classifier_VEC.erase(PD_Classifier_VEC.begin());
}

如您所见,前两行上方提供的注释工作正常,但是当我尝试使用 imshow 显示图像时,程序崩溃并显示损坏的双链表错误 !!这里出了什么问题?

为什么我无法显示此图像,如果POINT_MAT图像已损坏,前两行如何正常工作?

附言如果我从 j=57 启动程序,它工作正常,直到它完成并且没有出现错误,所以

//some calculation 

代码工作正常,我确信这一点。

我已经测试了许多其他函数,例如阈值,减法和...它适用于图像的数据部分,它们工作正常,但是当我添加一个适用于元数据+数据部分的函数时,损坏的双链表再次出现!!

cv::subtract(Point_MAT,Point_MAT,temp); //works fine because it only works on data part
Point_MAT.copyTo(Temp_MAT); //gives error cause it works on header part too ...

该错误来自标准 C 库,指示您已经损坏了堆。

具体来说,除非自己的代码中有匹配的addref(),否则不应在Cv::mat上调用release()Cv::mat的行为类似于Qt中常见的隐式共享值(如QImage),您不必担心手动管理其引用计数。

显而易见的建议是删除"一些计算"部分。对于更多图像,您按原样显示的代码应该可以工作(没有release()),而无需计算。

将你显示的代码转换为单独的单个文件项目,并确保它运行 - 因为它应该运行。然后,错误仅限于您的计算 - 它仅在您进行计算时才表现出来,这是计算问题的症状。

也许计算会分配内存?

下面是一个有效的、自包含的示例,它演示了显示的代码不仅正常,而且即使您一次在内存中存储一百张图像,一切正常。每个图像的大小为 2MB。

#include <QImage>
#include <QTemporaryFile>
#include <QDebug>
#include <vector>
#include <opencv2/opencv.hpp>
std::vector<cv::Mat> PD_Classifier_VEC;
void PD()
{
  cv::Mat Point_MAT = cv::Mat(PD_Classifier_VEC[0].size(),CV_8UC1,cv::Scalar::all(0));
  //Some Calculation //
  std::stringstream stream;
  stream<<Point_MAT<<"n";
  int Nonz = cv::countNonZero(Point_MAT);
  cv::imshow("Point_MAT",Point_MAT);
  PD_Classifier_VEC.erase(PD_Classifier_VEC.begin());
}
int main()
{
  QTemporaryFile file;
  file.setFileTemplate(file.fileTemplate() + ".jpg");
  const int N = 100;
  for(int j = 0 ; j < N ; j++)
  {
    file.open();
    QImage img(800, 600, QImage::Format_RGB32);
    img.save(&file);
    file.close();
    QString address = file.fileName();
    cv::Mat image = cv::imread(address.toStdString(),0);
    PD_Classifier_VEC.push_back(image);
  }
  while (!PD_Classifier_VEC.empty()) PD();
  cv::waitKey();
  return 0;
}

Kuba的回答中很好地描述了潜在的问题。

就我而言,我将cv::Mat作为参数传递给图像的函数。但是在主线程访问该垫子时,获取图像的工作线程已经删除了它。

解决方案是通过垫子的克隆。

    ...
    cv::Mat const img = recordImage();
    myWindow->setImage(img);
} // end of function, img will get deleted
    ...
    cv::Mat const img = recordImage();
    myWindow->setImage(img.clone());
} // img will get deleted, but the clone will persist