Home > Blockchain >  Pointers used as values in map corrupted after function finishes
Pointers used as values in map corrupted after function finishes

Time:02-15

I'm trying to store a map of VALUE to Node* but after each addEdge, the value for the added keys (Node*) changes.

One example is if I call addEdge(u, v), the map shows all the data correctly within the lifetime. If another call is made to addEdge(u, w), the keys u, v are present but the values are "corrupted"? Here's an example of the output: enter image description here

Sample code:

struct Node {
    VALUE value;
    Node* prev;
    Node* next;
};

class Graph {
    std::map<VALUE, Node*> nodes;
};

void Graph::addEdge(VALUE u, VALUE v) {
    Node* uNode;
    Node* vNode;

    if (nodes.count(u) == 0) {
        uNode = &Node{ u, nullptr, nullptr };
        nodes.emplace(u, uNode);
    } else {
        uNode = nodes.at(u);
    }

    if (nodes.count(v) == 0) {
        vNode = &Node{ v, nullptr, nullptr };
        nodes.emplace(v, vNode);
    } else {
        vNode = nodes.at(v);
    }

    uNode->next = vNode;
    vNode->prev = uNode;
}

I've tried calling nodes.emplace after assigning next, prev but it didn't fix it. Thanks!

EDIT Updated addEdge:

void addEdgeVALUE u, VALUE v) {
    Node* uNode;
    Node* vNode;
    bool isUNodePresent = true;
    bool isVNodePresent = true;

    if (nodes.count(u) == 0) {
        isUNodePresent = false;
        uNode = new Node(u, nullptr, nullptr);
    } else {
        uNode = &nodes.at(u);
    }

    if (nodes.count(v) == 0) {
        isVNodePresent = false;
        vNode = new Node(v, nullptr, nullptr);
    } else {
        vNode = &nodes.at(v);
    }

    uNode->next = vNode;
    vNode->prev = uNode;

    if (!isUNodePresent) nodes.emplace(u, *uNode);
    if (!isVNodePresent) nodes.emplace(v, *vNode);

}

CodePudding user response:

Your initial addEdge was taking the address of unnamed temporary objects, which is not valid C .

Your updated addEdge has nodes point to the leaked Nodes that you new, not the Nodes that are in the map.

You don't have to test for presence in the map, map::emplace doesn't overwrite existing items, and the return value holds a reference to the Node with that key.

struct Node {
    VALUE value;
    Node* prev;
    Node* next;
};

class Graph {
    std::map<VALUE, Node> nodes;
public:
    void addEdge(VALUE u, VALUE v);
};

void Graph::addEdge(VALUE u, VALUE v) {
    Node & uNode = nodes.emplace(u, { u }).first->second;
    Node & vNode = nodes.emplace(v, { v }).first->second;
    uNode.next = &vNode;
    vNode.prev = &uNode;
}
  • Related