【问题标题】:Corrupted double linked-list for opencv libraryopencv 库的损坏的双链表
【发布时间】:2014-04-03 15:24:39
【问题描述】:

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

Main.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();
          }
}

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());

}

如您所见,前两行上方提供的 cmets 工作正常,但是当我尝试使用 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 ...

【问题讨论】:

  • 显而易见的建议是删除“一些计算”部分。对于更多图像,它应该在没有计算的代码上工作(没有release())。
  • -1 因为您没有提供任何实际失败的代码。到目前为止的一切(release() 尽管)工作正常。我知道,我试过了。
  • 现在您知道不展示一个完整的、自包含的示例 是多么的低效。像你这样的问题一次又一次地出现在 SO 上,提问者总是一致地声称他们不需要需要提供任何其他代码。他们总是是错误的,他们这样做是在浪费他们的时间和回答者的时间。
  • 是的,我尽量不再重复...我今天学到了一些关于如何在 SO 中提供代码的重要知识...

标签: c++ qt opencv


【解决方案1】:

错误来自标准 C 库,表明您已损坏堆。

具体来说,您不应在Cv::mat 上调用release(),除非您在您自己的代码中有匹配的addref()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;
}

【讨论】:

  • 同样,Cv::mat 是一个合适的 C++ 类。当你完成使用它时,你会破坏它。这就是erase 所做的。暂时忘记addrefrelease 方法,它们仅在您想要干预mat 的内存管理的非常特定的情况下有用。别担心。
  • @Parsa 还有一种可能是你有巨大的图像并且你的堆用完了。你的图片有多大(以 MB 为单位)?
  • 最多在 1 到 2 兆字节之间..你能告诉我如何增加 qt 中的堆大小,以便我检查这是否是问题的根源?
  • 所以提出任何我可以测试的东西,看看我在哪里可以找到问题的根源......我在编程方面非常熟练......
  • 感谢问题出在一些opencv函数的序列中!我重写了它们,问题就解决了......
猜你喜欢
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
相关资源
最近更新 更多