c++ - 迭代器偶尔会出现段错误

标签 c++ opencv vector iterator 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;
    }
}

当这个函数执行时,大多数时候我会遇到段错误,但有时它会起作用并且结果如我所料。我知道 vector 包含元素。
那么您能想到造成这种行为的任何可能原因吗?

编辑:有趣的是,当使用这个函数的函数已经成功执行一次时,我可以一次又一次地重新执行它并且不会发生错误。

EDIT2:我仍然不知道为什么我会遇到迭代器的段错误,但如果没有它们,它会以某种方式工作:

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

最佳答案

您将迭代器递增两次。一旦来到这里:

for (auto it = Play::getInstance()->getFinder()->getLines().begin(); it != Play::getInstance()->getFinder()->getLines().end(); ++it)

一旦来到这里:

++it;

您可能会递增超过 end() 迭代器,从而导致未定义的行为。

编辑:

您的帖子中没有足够的信息来确定其他问题,尤其是我不知道所有的变量和函数是什么。我也不想爬过整个 git。

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

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

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

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

编辑2:

好吧,我快速浏览了您的存储库,发现 linefinder.cpp 中存在错误:

std::vector<cv::Vec4i> LineFinder::getLines()
{
    return lines;
}

getLines() 返回对同一容器的引用,它在每次调用时返回一个拷贝。因此,您一直在 for 循环中将一个容器的迭代器与另一个容器的迭代器进行比较。要么将定义更改为引用返回:

std::vector<cv::Vec4i>& LineFinder::getLines()
{
    return lines;
}

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

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

关于c++ - 迭代器偶尔会出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21069958/

相关文章:

c++ - 如何在 c 中返回一个 float 数组并将其保存为一个 float 数组以备后用?

c++ - 抛出 C++ 异常时在调试器中中断程序

c++ - "undefined behaviour"是否扩展到编译时?

android - 将 Mat 转换为 Blob,然后再转换回 Mat

r - 按组对 data.frame 执行基于向量的操作

c++ - 使用 boost::asio 配置 TCP keep_alive

c++ - 找不到 OpenCV haarcascade_frontalface_alt.xml

python - 如何在OpenCV Python中设置框架的高度和宽度

c++ - 当 vector 大小更改时迭代 std::vector。 (C++)

java - 如何在运行时根据用户/程序员的需要自动增加数组的大小?