【问题标题】:Why does renaming my variable prevent a segfault?为什么重命名我的变量会防止出现段错误?
【发布时间】:2012-07-28 17:59:16
【问题描述】:

我有一个单一的深度优先搜索算法来遍历我的图,给定一个起始节点的迭代器。

文档摘要:

  • GraphIterGraph::iteratortypedef
  • Graph扩展 map<string, Node>
  • start->second.edges() 返回set<string>

如果start->second.edges()size0,则此代码会导致分段错误:

(为简洁起见,我已经截断了不相关的部分,包括递归调用。)


错误代码

void Graph::dfs(GraphIter start)
{
    cout << "EDGES SIZE: " << start->second.edges().size() << endl;

    for (set<string>::iterator it = start->second.edges().begin();
          it != start->second.edges().end(); ++it)
    {
        GraphIter iter = this->find(*it);     // <--- SEGMENTATION FAULT
    }
}

现在看看当我将start-&gt;second.edges() 拉入一个局部变量时会发生什么:不再有段错误!

这是不产生段错误的代码:


好代码

void Graph::dfs(GraphIter start)
{
    set<string> edges = start->second.edges();       // <--- MAGIC TRICK
    cout << "EDGES SIZE: " << edges.size() << endl;

    for (set<string>::iterator it = edges.begin();
          it != edges.end(); ++it)
    {
        GraphIter iter = this->find(*it);
    }
}

所以区别在于,在好的代码中,当字符串集合的size(来自edges()方法)为0时,for在第二种情况下永远不会进入循环。但在第一种情况下,for 循环仍然至少执行一次,直到它意识到它无法取消引用 it 变量。

为什么这些不同?他们不是访问相同的内存部分吗?

【问题讨论】:

    标签: c++ iterator segmentation-fault iteration


    【解决方案1】:

    因为edges() 按值返回set,所以start-&gt;second.edges().begin()start-&gt;second.edges().end() 将迭代器返回到不同的容器,因为每次调用edges() 都会返回一个新的set

    通过使用命名变量创建单个副本,您可以确保迭代器都来自同一个容器,并且您可以有效地从 begin() 迭代到 end()

    【讨论】:

    • 这就是为什么!谢谢。我没有考虑到,虽然迭代器是一个指针,但随后调用的 edges() 方法是按值返回,而不是按引用返回。
    【解决方案2】:

    可能是start-&gt;second.edges() 按值返回std::set&lt;std::string&gt;。这将使循环中的迭代器不兼容并导致未定义的行为。

    你的“魔术”

    set<string> edges = start->second.edges();
    

    确保您在同一个容器“edges”上进行迭代。

    您可以通过引用返回 Node::edges() 来修复它:

    const std::set<std::string>& edges() const { .... }
    

    【讨论】:

    • ... 并将iterator 更改为const_iterator
    • @CharlesBailey ...或者只使用auto it = ... :)
    猜你喜欢
    • 2013-02-11
    • 2018-01-07
    • 1970-01-01
    • 2020-02-16
    • 2018-01-28
    • 1970-01-01
    • 2021-01-14
    • 2023-04-10
    相关资源
    最近更新 更多