0

我有一个简单的洪水填充功能,除了它在运行时因过多的释放而崩溃。

#include <vector>
cv::Mat fillLayer(cv::Mat filledEdge, int y, int x, int oldColor, float newColor){
    cv::Size shape = filledEdge.size();
    int h = shape.height;
    int w = shape.width;

    std::vector<int> theStackx = {x};
    std::vector<int> theStacky = {y};


    while (theStacky.size() > 0){
        y = theStacky.back();
        x = theStackx.back();
        theStacky.pop_back();
        theStackx.pop_back();

        if (x == w){
            continue;
        }
        if (x == -1){
            continue;
        }
        if (y == -1){
            continue;
        }
        if (y == h){
            continue;
        }

        if (filledEdge.at<float>(y, x) != oldColor){
            continue;
        }

        filledEdge.at<float>(y, x) = newColor;

        //up
        theStacky.push_back(y + 1);
        theStackx.push_back(x);
        //down
        theStacky.push_back(y - 1);
        theStackx.push_back(x);
        //right
        theStacky.push_back(y);
        theStackx.push_back(x + 1);
        //left
        theStacky.push_back(y);
        theStackx.push_back(x - 1);
    }
    return filledEdge;

}

贯穿floodfill的函数是fillSurface。它贯穿 Mat 中的所有像素,并为每个 Floodfill 填充不同的颜色

fillSurface(cv::Mat filledEdge, int oldColor) {
    std::vector<float> layers; //list all the different colors in mat
    cv::Size shape = filledEdge.size();
    int h = shape.height;
    int w = shape.width;
    float newColor;
    // run through all the pixels in Mat
    for(int y = 0; y!= h; y++){
        for(int x = 0; x!= w; x++){
            // only run floodfill if current pixel is oldColor
            if (filledEdge.at<float>(y, x) == oldColor){
                //newColor is random float to fill in to floodfill
                newColor = static_cast <float> ((rand()) / (static_cast <float> (RAND_MAX/253)) + 1); 
                // add newColor to list of layers
                layers.push_back(newColor);
                //run flood fill replacing old color with new color
                filledEdge = fillLayer(filledEdge, y, x, oldColor, newColor);

            }
        }
    }
}

这是我收到的错误:

Incorrect checksum for freed object 0x7fea0d89dc00: probably modified after being freed.

我所做的调试远是在 malloc_error_break() 上设置一个断点,以查看我在哪里得到了中断。它确实导致了洪水填充功能。

在此处输入图像描述

我想知道是否有办法解决这个问题。如果没有,最好的选择是什么?

4

1 回答 1

1

如果没有 MCVE,我无法直接重现您的问题,而且我自己也不知道 CV。但我可以做出一些可能有所帮助的猜测。

运行时错误指出“已​​释放对象的校验和不正确......:可能在被释放后修改。”

给您的第一个提示是,像这样的堆检查通常仅在发生堆操作时进行,而不是在发生损坏时进行。您的代码中没有任何显式的堆操作(例如,newdelete)。这里的堆使用来自标准库 ( vector) 和 cv ( Mat) 中记录良好且经过良好测试的数据结构。

第二个提示是probably modified after being freed,但这并不完整——另一种可能性是一些代码超出了它的范围——缓冲区溢出或不正确的数组索引或类似的东西。

最后一点将我们带到 Mat 类的 CV 文档中,该文档没有提到如果您对 Mat 索引不当会发生什么。它确实有关于确保您使用正确的元素类型访问的警告,否则可能会出错。这些东西加在一起可能是一个非常强烈的暗示,如果你不正确地访问 Mat 可能会发生坏事。就像,如果你正在写作,可能是内存损坏。

这些东西,连同我上面关于你声明变量但不使用它们的评论——h以及w你认为你将使用什么h以及w用于什么——应该让你在弄清楚堆是如何被破坏到运行时系统抱怨它的地方。

剧透警报(为获得最佳结果,请在解决问题后阅读):

写在边界之外,Mat因为您从不检查索引的边界以防止它们超出限制,并且显然Mat::at也没有检查(至少,文档没有说它确实如此 - 您可以通过实验来验证) .

于 2018-11-15T16:43:15.770 回答