从队列

时间:2017-01-27 16:20:19

标签: c++ c++11 segmentation-fault queue

我有以下功能:

std::vector<Node> BFS(Graph g, Node source, Node target) {
    std::queue<std::vector<Node> > q;
    std::vector<Node> path = {source};
    q.push(path);
    while (!q.empty()) {
        std::vector<Node> cur_path = q.front();
        q.pop();
        Node cur_node = cur_path[cur_path.size() - 1];
        if (cur_node.data == target.data) {
            return cur_path;
        }
        // for (int i = 0; i < g.edge_map[cur_path].size(); i++) {
        //     std::vector<Node> new_path = cur_path;
        //     new_path.push_back(g.edge_map[cur_path][i]);
        //     q.push(new_path);
        // }
    }
}

现在,我并没有声称这会完成搜索,我只是想知道它为什么会导致分段错误。我知道这是因为我有q.pop();有点,但为什么?这是因为向量本身就是引用吗?如果需要,我可以包含更多代码,只是尝试将问题封装起来。

编辑:这是main()驱动程序:

int main(int argc, char **argv) {
    // double normals[][3] = {
    //    #include "normals.txt"
    // };
    Graph g;
    Node n0 {0, "red"};
    Node n1 {1, "yellow"};
    Node n2 {2, "black"};
    Node n3 {3, "black"};
    Node n4 {4, "red"};
    Node n5 {5, "yellow"};
    Node n6 {6, "black"};
    Node n7 {7, "black"};
    Node n8 {8, "red"};
    Node n9 {9, "yellow"};
    Node n10 {10, "black"};
    Node n11 {11, "black"};

    g.add_neighbor(n0, n1, true);
    g.add_neighbor(n0, n2, true);
    g.add_neighbor(n0, n3, true);
    g.add_neighbor(n2, n4, true);
    g.add_neighbor(n4, n5, true);
    g.add_neighbor(n4, n6, true);
    g.add_neighbor(n4, n7, true);
    g.add_neighbor(n6, n8, true);
    g.add_neighbor(n8, n9, true);
    g.add_neighbor(n8, n10, true);
    g.add_neighbor(n8, n11, true);
    BFS(g, n0, n11);
    return 0;
}

给出:

graph. yup
Segmentation fault (core dumped)

FWIW,我的图形有一个edge_map成员,它是一个以Node结构为键的映射,Node的向量结构为值,表示图形邻接列表。构造函数输出'图。是的,如果您需要更多信息,请告诉我

编辑2:我只是将其余部分用于完整性,对于冗长而感到遗憾,但我正在努力理解为什么会这样。

graph.h:

#include <iostream>
#include <map>
#include <vector>

struct Node {
    int data;
    std::string color;
};

inline bool operator<(const Node & left, const Node & right) {
    return left.data < right.data;
}

class Graph {
public:

    std::map< Node, std::vector<Node> > edge_map;

    Graph();

    void add_neighbor(Node cur_node, Node new_node, bool both_ways=false);

    void remove_neighbor(Node cur_node, Node del_node, bool both_ways=false);

    void print_neighbors(Node cur_node);

    virtual ~Graph();
};

graph.cpp:

#include <iostream>
#include <vector>
#include <algorithm>
#include "graph.h"
#include <map>

Graph::Graph() {
    std::cout << "graph. yup" << std::endl;
}


void Graph::add_neighbor(Node cur_node, Node new_node, bool both_ways) {
    edge_map[cur_node].push_back(new_node);
    if (both_ways) {
        edge_map[new_node].push_back(cur_node);
    }
}

void Graph::remove_neighbor(Node cur_node, Node del_node, bool both_ways) {
    // TODO: convert vector values in map of <Node, vector<Node> > into maps, so this function can be easy and have sensible complexity
    std::cout << "Not implemented yet." << std::endl;
    // if (both_ways) {
    //     edge_map[del_node].remove(cur_node);
    // }
    //this->edge_map[cur_node].erase(std::remove(this->edge_map[cur_node].begin(), this->edge_map[cur_node].end(), del_node), this->edge_map[cur_node].end());
}

void Graph::print_neighbors(Node cur_node) {
    for (int i = 0; i < edge_map[cur_node].size(); i++) {
        std::cout << edge_map[cur_node][i].data << " " << edge_map[cur_node][i].color << std::endl;
    }
}

Graph::~Graph() {
    std::cout << "ded graph :(" << std::endl;
}

任何一般的提示也值得赞赏,我是绿色的。

2 个答案:

答案 0 :(得分:1)

一个很大的,明显的错误:

您的BFS函数不会返回所有控制路径的值,即使它应该返回std::vector<Node>。因此,您的程序具有未定义的行为。 BFS返回的唯一路径是while循环中的条件语句:

 if (cur_node.data == target.data) {
            return cur_path;

但是,如果在运行外部cur_node.data循环期间target.data永远不等于while,则不会返回,从而触发未定义的行为(在您的情况下,是一个分段错误)。

运行程序here, using the triggering output statement, "I'm in trouble!!"表明您正在导致未定义的行为。请注意,使用的编译器是Visual Studio 2015。

但为了显示未定义行为的后果,请注意gcc as shown here只会在不打印消息的情况下崩溃。要让它打印消息,必须用std::endl刷新缓冲区以查看“麻烦!!”字符串as seen here

鉴于所有这些,因为你必须返回一些东西,你必须决定在找不到节点的情况下返回什么。您可以返回std::vector<Node>(),但调用者BFS如何确定此节点是否是存在的节点?我认为你需要理清BFS关于该函数的输出应该表示什么的基本规则。

此外:

Node cur_node = cur_path[cur_path.size() - 1];

可能只是:

Node cur_node = cur_path.back();

答案 1 :(得分:-1)

(我没有足够的声誉来添加评论)

据我所知,可能会发生什么:

  • q.pop调用std :: vector

  • 的析构函数
  • ~std :: vector销毁每个节点

  • 也许Node析构函数做了非法的事情?