简体   繁体   中英

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.

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). 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.

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. 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. It crashes when trying to .insert() the values in instance_graph_ids, which is the map structure I wrote about before. 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. 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. 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

You should change first_node_iterator->first to 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"
use std::vector to store nodes in the SmartGraph ,
there are only two elements on std::vector when graph.addEdge ,
you use first_node_iterator->first(value is 10000) as it subscript, which is out of range.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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