偶尔使用迭代器进行分段错误

Bla*_*mba 0 c++ opencv iterator vector segmentation-fault

我目前正在开发一个关于一个应用程序的项目,它能够从绘制的图像中创建一个可玩的游戏关卡(可以在这里找到:Github).为此,我使用openCV进行图像处理.
我的问题是一个函数,它应该将检测到的线条(水平面上的"墙壁")绘制到图像上.

void LineFinder::drawDetectedLines( cv::Scalar color)
{
    for (auto it = Play::getInstance()->getFinder()->getLines().begin(); it != Play::getInstance()->getFinder()->getLines().end(); ++it)
    {
        // The lines are stored in an std::vector<cv::Vec4i>, 
        // so basically in a vector which contains vectors with 4 elements each
        cv::Point pt1((*it)[0], (*it)[1]);
        cv::Point pt2((*it)[2], (*it)[3]);

        // draws a line from pt1 to pt2
        cv::line(Play::getInstance()->getFinder()->getImage(), pt1, pt2, color);

        ++it;
    }
}
Run Code Online (Sandbox Code Playgroud)

当这个函数执行时,大多数时候我都会遇到分段错误,但有时它会起作用,结果就像我预期的那样.我知道向量包含元素.
那么你能想到的这种行为有什么可能的原因吗?

编辑:有趣的是,当使用此函数的函数已成功执行一次时,我可以反复执行它,并且不会发生错误.

编辑2:我仍然不知道为什么我用迭代器得到分段错误,但没有它们它以某种方式工作:

void LineFinder::drawDetectedLines( cv::Scalar color)
{
    for (int i = 0; i < Play::getInstance()->getFinder()->getLines().size(); ++i)
    {
        cv::Point pt1(Play::getInstance()->getFinder()->getLines()[i][0], Play::getInstance()->getFinder()->getLines()[i][1]);
        cv::Point pt2(Play::getInstance()->getFinder()->getLines()[i][2], Play::getInstance()->getFinder()->getLines()[i][3]);

        cv::line(Play::getInstance()->getFinder()->getImage(), pt1, pt2, color);
    }
}
Run Code Online (Sandbox Code Playgroud)

Nab*_*bla 6

您将迭代器增加两次.来到这里:

for (auto it = Play::getInstance()->getFinder()->getLines().begin(); it != Play::getInstance()->getFinder()->getLines().end(); ++it)
Run Code Online (Sandbox Code Playgroud)

在这里:

++it;
Run Code Online (Sandbox Code Playgroud)

您可能会超过end()迭代器,导致未定义的行为.

编辑:

您的帖子中没有足够的信息来识别其他问题,尤其是我不知道所有变量和功能是什么.我也不想爬过整个git.

所以这里有一些可能的问题:

  1. 是否Play::getInstance()->getFinder()->getLines()保证始终返回对同一容器的引用?

  2. 返回的容器是否保证在迭代时不被修改?

  3. 存储在容器中的对象是否保证是数组/向量/ ...至少有4个元素?

EDIT2:

好吧,我简要介绍了你的存储库,linefinder.cpp中有错误:

std::vector<cv::Vec4i> LineFinder::getLines()
{
    return lines;
}
Run Code Online (Sandbox Code Playgroud)

getLines()没有返回到相同的容器的引用,它在每次调用返回一个副本.所以你继续比较一个容器的迭代器和你的for循环中另一个容器的迭代器.将定义更改为引用返回:

std::vector<cv::Vec4i>& LineFinder::getLines()
{
    return lines;
}
Run Code Online (Sandbox Code Playgroud)

或者在构造迭代器之前保存返回:

auto lines = Play::getInstance()->getFinder()->getLines();
for (auto it = lines.begin(); it != lines.end(); ++it)
{
Run Code Online (Sandbox Code Playgroud)