【问题标题】:Sysmalloc error with opencvSysmalloc错误与opencv
【发布时间】:2017-03-03 11:31:43
【问题描述】:

我在使用 opencv 时遇到 sysmalloc 错误。当我调试时发现错误发生在这里:

sm = cv::Mat::zeros(h,w,img.type());

其中 h 和 w 分别是 img 行和 w 列。我展示了它们,它们还可以。这是整个函数:

cv::Mat gsmooth(cv::Mat img,int sigma,int radius,std::string methode)
{
    cv::Mat sm;
    std::vector<double> hcol;
    std::vector<double> hrow;
    if(sigma == NULL)
    {
        sigma =1;
    }
    if(radius == NULL)
    {
        radius = ceil(2.5*sigma);
    }
    if(methode.c_str()==NULL)
    {
        methode ="none";
    }

    if(sigma == 0)
    {
        sm = img;
    }
    else
    {

        hcol= gKernel(2*radius+1,sigma);
        hrow= gKernel(2*radius+1,sigma);
        int h=img.rows;
        int w=img.cols;
        int c=img.channels();
        switch (c)
        {
                case 1:
                     sm= cv::Mat::zeros(h,w,img.type());
                    break;
                case 2:
                     sm= cv::Mat::zeros(h,w,CV_32SC2);
                    break;
                default:
                     sm= cv::Mat::zeros(h,w,CV_32SC3);
        }
        if(!methode.compare(std::string("mirror")))
        {
            cv::Mat mattmp=mirror(img,radius,radius);
            sm=conv2(mattmp,hcol,hrow);

            int ma=img.rows;
            int na=img.cols;
            int nb=hcol.size();
            int mb=hrow.size();
            sm=sm.rowRange((mb-1)/2,(mb-1)/2+ma).colRange((nb-1)/2,(nb-1)/2+na);
        }
        else
        {
            cv::Mat sm_;
            sm_=conv2(img,hcol,hrow);
            int H=sm.rows;
            int W=sm.cols;
            int h=img.rows;
            int w=img.cols;
            int y=ceil(H/h);
            int x=ceil(W/w);
            sm=sm.rowRange(y,y+h).colRange(x,x+w);
        }

    }
    hcol.clear();
    hrow.clear();
    return(sm);

}

该函数由另一个带有 cv::Mat img、两个 int 和“mirror”或“none”的 .cpp 调用。论点似乎是正确的:img 矩阵已正确加载,而另一个只是 int。

完整的错误是:*malloc.c:2372: sysmalloc: Assertion '(old_top== (((mbinptr) (((char *) &amp;((av)-&gt;bins[((1) - 1)*2)) -__builtin_offsetof (struct malloc_chunk, fd)))) &amp;&amp; old_size == 0) || ((unsigned long) (old_size) &gt;= (unsigned long)((((__builtin_offsetof (struct malloc_chunk,fd_nextsize))+((2*(sizeof(size_t))) -1)) &amp; ~((2*sizeof(size_t))) -1)))&amp;&amp; ((old_top)-&gt; size &amp; 0x1) &amp;&amp; ((unsigned long) old_end &amp; pagemask) ==0)' failed.*

我在 ubuntu 14.04.5 上使用 Qt 5.2、gcc 4.6 和 g++ 4.4,由于与 braid lib 的兼容性问题,我必须使用 opencv 2.4.13。

我确定我的错误是愚蠢的,也许我不能像这样声明一个零矩阵,但我不知道该怎么做,而且我没有找到任何与此问题相关的话题。

一般来说,我对使用 opencv 的 malloc 问题感到很困惑。大多数时候,我使用函数在参数中获取 cv::Mat 并使用它返回在函数内部声明的新矩阵,如下所示:

cv::Mat function somefunction(cv::Mat img, some arguments)
{
   cv::Mat res;
   //operations 
   return(res);
}

我这样调用函数:new_img=some_function(img, some_arguments);

我想知道这是否是正确的做法?

我希望我已经足够具体了,如果您需要更多信息,请不要犹豫。

编辑:使用 Valgrind 我发现当我尝试使用 gKernel 时会出现问题。 事实上gsmooth 被调用了两次,第一次一切正常,第二次调用时发生崩溃。 Valgrind 在函数的第一行指出了一个 SIGSEGV 错误:std::vector&lt;double&gt; kernel(size);

这是整个函数:

std::vector<double> gKernel(int size, float sigma)
{
   std::vector<double>kernel(size);
   double r,s =2.0* sigma * sigma;
   double sum=0.0;
   int radius=(size -1)/2;
   int index=0;
   for(int y=-radius; y<=radius;y++)
   {
       r=sqrt(y*y);
       kernel[index]=(exp(-(r*r)/s))/(sqrt(2*M_PI*s));
       sum+=kernel[index];
       index++;
   }
   for(int i=0;i<size;i++)
   {
       kernel[i]/=sum;
   }
   return(kernel);
}

我不明白为什么声明向量可能会导致 Segfault? 正如您在我的 gsmooth 函数中看到的,gKernel 的调用大小为 = 2*radius +1,第一次调用时 sigma 等于 60,第二次调用时 sigma 等于 50。

至少我知道我不应该使用 '=' 复制 cv::Mat,而应该使用 clonecopyTo 以避免混淆像素的指针。

【问题讨论】:

    标签: c++ opencv matrix malloc


    【解决方案1】:

    可能您在某处损坏了内存,但不是在上面的代码中。 cv::Mat::zeros 的用法看起来不错。

    使用Valgrind查找问题原因。

    更新

    我通过在前面的代码行中将 m.at=someint 替换为 m.at=someint 解决了我的问题

    之所以有效,是因为您的 Mat m 不是由 double 类型表示的。 m 应该具有类型 CV_64F 或类似于访问 double 元素。实际上您的Mat m 类型是CV_8U,它对应于您在修复中使用的uchar

    要更改Mat m 的类型,您可以使用convertTo 方法。

    【讨论】:

    • 谢谢,我试过 Valgrind,这正是我需要的。我会用更多信息更新我的帖子(或者可能是解决方案?)
    • @RomainMartin 我确定问题不在gKernel 函数中。看起来内存在gsmooth 执行之前已损坏。例如。检查图片加载功能。
    • 我相信你,但我找不到哪里有问题。图片加载功能看起来不错,一开始只调用一次,我尝试用填充矩阵替换加载的图像,但仍然有相同的结果......我会再次检查并发布如果我发现任何线索。
    • 我通过在前面的代码行中将m.at&lt;double&gt;=someint 替换为m.at&lt;uchar&gt;=someint 解决了我的问题。但是我不明白为什么它与 uchar 而不是 double 一起工作,在大多数情况下我不需要 double 矩阵,所以它没有用 deal 。使用 m 除了增加我的图片的大小。但是在某些部分我至少需要有浮动数字,所以我希望我不会有损坏的内存问题。如果有人可以解释为什么它不起作用,我会让我的问题几天没有答案。无论如何感谢尼基塔的帮助,你是对的。
    • @RomainMartin 看起来原因对我来说很清楚。请检查答案更新
    猜你喜欢
    • 2015-10-13
    • 1970-01-01
    • 2012-06-13
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    相关资源
    最近更新 更多