简体   繁体   English

C ++ - 将值插入std :: map时出现分段错误

[英]C++ - Segmentation fault when inserting values into std::map

I'm trying to build a graph instance parser in C++ which takes the graph nodes as an input and inserts them into a SmartGraph class defined by the LEMON library. 我正在尝试用C ++构建一个图形实例解析器,它将图形节点作为输入并将它们插入到由LEMON库定义的SmartGraph类中。

The library doesn't allow me to insert nodes with a specific ID (as far as I've seen in the documentation) so I've created a parallel structure to store the relationships between the node IDs of the input file and the node IDs of the actual graph in my code (there might be a clever way to go around this, but I haven't put much thought on it and it sounds OK to me, as long as the instances aren't so massive that I run out of memory which is almost impossible). 该库不允许我插入具有特定ID的节点(据我在文档中看到),所以我创建了一个并行结构来存储输入文件的节点ID和节点ID之间的关系在我的代码中的实际图形(可能有一个聪明的方法来解决这个问题,但我没有太多考虑它,这对我来说听起来不错,只要实例不是那么大,我用完了记忆几乎是不可能的)。 For this, I am using a std::map which holds the input file ID as the key, and the graph node ID as the value. 为此,我使用的是std :: map,它将输入文件ID保存为键,图形节点ID保存为值。

This std::map is crashing in iteration number 239 of the loop that reads lines from the input file if I just execute the program, and it gets to 2252 if I check it with Valgrind, which makes me think I must be making a really big oversight and leaking memory somewhere, but I can't figure it out. 如果我只是执行程序,此std :: map就会在循环的迭代号239中崩溃,该循环将从输入文件中读取行,如果我用Valgrind对其进行检查,它将达到2252,这使我认为我必须做出一个真正的在某处有大的疏忽和泄漏记忆,但我无法弄明白。 The code is as follows 代码如下

#include <lemon/smart_graph.h>
#include <lemon/concepts/graph.h>
#include <iostream>
#include <fstream>
#include <map>
#include <string>

using std::cout;
using std::cin;
using std::getline;
using std::vector;
using std::string;
using std::stringstream;
using std::exception;
using std::ifstream;
using std::ios;
using std::map;

using lemon::SmartGraph;

map<int, int> instance_graph_ids;
map<int, int>::iterator it;
SmartGraph graph;
ifstream input_instance("instance.txt", ios::in);
string current_line;
while (getline (input_instance, current_line))
    {
        stringstream stream(current_line);
        string buffer;
        vector <int> separated_nodes;
        while(getline(stream, buffer, '\t')){
            separated_nodes.push_back(stoi(buffer));
        };
        for (int node : separated_nodes){
            it = instance_graph_ids.find(node);
            if (it == instance_graph_ids.end())
                {
                    int new_node_id;
                    SmartGraph::Node new_node = graph.addNode();
                    new_node_id = graph.id(new_node);
                    instance_graph_ids.insert({ node, new_node_id });
                };
        };
        auto first_node_iterator = instance_graph_ids.find(separated_nodes[0]);
        auto second_node_iterator = instance_graph_ids.find(separated_nodes[1]);
        graph.addEdge( graph.nodeFromId(first_node_iterator -> first),graph.nodeFromId(second_node_iterator -> second));
    }

I know this is pretty ugly but I'm trying to get it to work before I start finessing so bear with me here. 我知道这很丑陋,但我想在开始做之前让它上班,所以在这里忍受我。 node is the ID of the node in the input file, represented as an integer. node是输入文件中节点的ID,以整数表示。 It crashes when trying to .insert() the values in instance_graph_ids, which is the map structure I wrote about before. 当尝试.insert()instance_graph_ids中的值时崩溃,这是我之前写过的地图结构。 I've checked this with gdb and both node and new_node_id are normal integers, and the existing values on instance_graph_ids look OK to me, too. 我用gdb检查了这个,并且node和new_node_id都是正常整数,而instance_graph_ids上的现有值对我来说也很合适。 Trying to call find() or insert() in instance_graph_ids in gdb returns an "Attempt to take address of value not located in memory" error. 尝试在gdb中的instance_graph_ids中调用find()或insert()会返回“尝试获取不在内存中的值的地址”错误。 What am I missing here? 我在这里想念什么?


Edited with a full example. 用完整的示例进行编辑。 A sample instance can be downloaded from https://snap.stanford.edu/data/oregon1_010331.txt.gz 可以从https://snap.stanford.edu/data/oregon1_010331.txt.gz下载示例实例

You should change first_node_iterator->first to first_node_iterator->second 您应该first_node_iterator->firstfirst_node_iterator->second更改为first_node_iterator->second

graph.addEdge(graph.nodeFromId(first_node_iterator->second),
              graph.nodeFromId(second_node_iterator->second));

For example, when processing the first line of "10000 4725" 例如,当处理第一行“10000 4725”时
use std::vector to store nodes in the SmartGraph , 使用std :: vector存储SmartGraph节点,
there are only two elements on std::vector when graph.addEdge , graph.addEdge ,std :: vector上只有两个元素,
you use first_node_iterator->first(value is 10000) as it subscript, which is out of range. 你使用first_node_iterator-> first(value是10000)作为下标,这超出了范围。

Modified code: 修改后的代码

#include <lemon/smart_graph.h>
#include <lemon/concepts/graph.h>
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <assert.h>

using std::cout;
using std::cin;
using std::getline;
using std::vector;
using std::string;
using std::stringstream;
using std::exception;
using std::ifstream;
using std::ios;
using std::map;

using lemon::SmartGraph;

int main()
{
    map<int, int> instance_graph_ids;
    map<int, int>::iterator it;
    SmartGraph graph;
    ifstream input_instance("instance.txt", ios::in);
    string current_line;

    while (getline (input_instance, current_line)) {
        stringstream stream(current_line);
        string buffer;
        vector <int> separated_nodes;

        while (getline(stream, buffer, '\t')) {
            separated_nodes.push_back(stoi(buffer));
        };

        for (int node : separated_nodes) {
            it = instance_graph_ids.find(node);

            if (it == instance_graph_ids.end()) {
                int new_node_id;
                SmartGraph::Node new_node = graph.addNode();
                new_node_id = graph.id(new_node);
                instance_graph_ids.insert({ node, new_node_id });
            };
        };

        auto first_node_iterator = instance_graph_ids.find(separated_nodes[0]);
        auto second_node_iterator = instance_graph_ids.find(separated_nodes[1]);

        assert(first_node_iterator->second < graph.nodeNum());
        graph.addEdge(graph.nodeFromId(first_node_iterator->second),
                      graph.nodeFromId(second_node_iterator->second));
    }

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM