doubly_linked_list::~doubly_linked_list()
{
list_item* current = head;
while (current)
{
list_item* next = current->Get_Next();
delete current;
current = next;
}
}
I am writing a dynamic graph in C++ with the usage of a doubly linked list to save the Graph nodes, however my code keeps on failing as it calls the destructor more times than it should be calling it, for example, during my destructor for the graph
Dynamic_Graph::~Dynamic_Graph()
{
edges.~doubly_linked_list();
nodes.~doubly_linked_list();
}
the destructor for the doubly linked list is called more than 2 times, despite it being called explicitly twice.
then i have the function for insertion of an edge:
Graph_Edge* Dynamic_Graph::Insert_Edge(Graph_Node* from, Graph_Node* to)
{
Graph_Edge* new_edge = new Graph_Edge(from, to);
from->Get_out_Nodes().List_Insert_After(to, from->Get_out_Nodes().Get_Tail());
to->Get_in_Nodes().List_Insert_After(from, to->Get_in_Nodes().Get_Tail());
edges.List_Insert(new_edge);
return new_edge;
}
after adding the to node to the adjacency list of the from node the code unexplainably calls the destructor for a doubly linked list and deletes this insertion, however i am not sure why.
here are the headers for the graph and the linked list:
class doubly_linked_list
{
private:
list_item* head;
list_item* tail;
public:
doubly_linked_list() { this->head = NULL; this->tail = NULL; }
doubly_linked_list(list_item* head){ this->head = head; this->tail = NULL; }
~doubly_linked_list();
list_item* Get_Head() { return head; }
list_item* Get_Tail() { return tail; }
void Set_Head(list_item* h) { head = h; }
void List_Insert(list_item* x);
void List_Insert_After(list_item* x, list_item* y);
void List_Delete(list_item* x);
};
class Dynamic_Graph
{
protected:
doubly_linked_list edges;
doubly_linked_list nodes;
public:
Dynamic_Graph() { edges = doubly_linked_list(); nodes = doubly_linked_list(); }
~Dynamic_Graph();
Graph_Node* Insert_Node(unsigned node_key);
void Delete_Node(Graph_Node* node);
Graph_Edge* Insert_Edge(Graph_Node* from, Graph_Node* to);
void Delete_Edge(Graph_Edge* edge);
Rooted_Tree* SCC() const;
Rooted_Tree* BFS(Graph_Node* source) const;
};
any help would be welcome
EDIT: i removed the calls to the destructors, however i still am getting a destructor call in the insert after function and i am not sure why.
EDIT 2: adding more relevant lines of code:
Graph_Edge* Dynamic_Graph::Insert_Edge(Graph_Node* from, Graph_Node* to)
{
Graph_Edge* new_edge = new Graph_Edge(from, to);
from->Get_out_Nodes().List_Insert_After(to, from->Get_out_Nodes().Get_Tail());
to->Get_in_Nodes().List_Insert_After(from, to->Get_in_Nodes().Get_Tail());
edges.List_Insert(new_edge);
return new_edge;
}
this is the function that triggers the error where it access a deleted pointer despite it not supposed to be deleted, it triggers after finishing inserting the "to" node to the "from" node adjacency list.
void doubly_linked_list::List_Insert_After(list_item* x, list_item* y)
{
if (!y)
{
head = x;
tail = x;
return;
}
if (y == tail)
{
tail = x;
}
if (y->Get_Next())
{
y->Get_Next()->Set_Prev(x);
}
x->Set_Next(y->Get_Next());
x->Set_Prev(y);
y->Set_Next(x);
}
this function is the insert after function in the doubly linked list.
EDIT 3: i tried to recrating the issue via the smallest amount of possible function, this is what i got:
#pragma once
#include < cstddef >
class List_Item
{
protected:
List_Item* next;
List_Item* prev;
public:
List_Item(): next(NULL), prev(NULL) {}
List_Item* Get_Next() { return next; }
List_Item* Get_Prev() { return prev; }
void Set_Next(List_Item* next) { this->next = next; }
void Set_Prev(List_Item* prev) { this->prev = prev; }
List_Item(const List_Item& item) : next(item.next), prev(item.prev){}
List_Item& operator=(const List_Item& item) { this->next = item.next; this->prev = item.prev; return *this; }
};
class Doubly_Linked_List
{
protected:
List_Item* head;
List_Item* tail;
public:
Doubly_Linked_List() : head(NULL), tail(NULL) {}
~Doubly_Linked_List();
List_Item* Get_Head() { return head; }
List_Item* Get_Tail() { return tail; }
void Set_Head(List_Item* h) { head = h; }
void Set_Tail(List_Item* t) { tail = t; }
void insert(List_Item* item);
void insert_after(List_Item* item, List_Item* after);
Doubly_Linked_List(const Doubly_Linked_List& list) : head(list.head), tail(list.tail) {}
Doubly_Linked_List& operator=(const Doubly_Linked_List& list) { this->head = list.head; this->tail = list.tail; return *this; }
};
Doubly_Linked_List::~Doubly_Linked_List()
{
List_Item* item = head;
while (item)
{
List_Item* next = item->Get_Next();
delete item;
item = next;
}
}
void Doubly_Linked_List::insert(List_Item* item)
{
item->Set_Next(head);
if (head)
head->Set_Prev(item);
if (!head)
tail = item;
head = item;
item->Set_Prev(NULL);
}
void Doubly_Linked_List::insert_after(List_Item* item, List_Item* after)
{
if (!after)
{
head = item;
tail = item;
return;
}
if (after->Get_Next())
{
after->Get_Next()->Set_Prev(item);
}
else
{
tail = item;
}
item->Set_Next(after);
item->Set_Prev(after);
after->Set_Next(item);
}
#pragma once
#include "List_Item.h"
#include"Doubly_Linked_List.h"
class Graph_Node :
public List_Item
{
protected:
const unsigned key;
Doubly_Linked_List in_nodes;
Doubly_Linked_List out_nodes;
public:
Graph_Node(unsigned key): key(key) {}
Doubly_Linked_List Get_In_Nodes() { return in_nodes; }
Doubly_Linked_List Get_Out_Nodes() { return out_nodes; }
};
class Graph_Edge :
public List_Item
{
protected:
Graph_Node* from;
Graph_Node* to;
public:
Graph_Edge(Graph_Node* f, Graph_Node* t): from(f), to(t) {}
Graph_Node* Get_From() { return from; }
Graph_Node* Get_To() { return to; }
};
int main()
{
unsigned node_key = 1;
Graph_Node* from = new Graph_Node(node_key++);
Graph_Node* to = new Graph_Node(node_key++);
from->Get_Out_Nodes().insert_after(to, from->Get_Out_Nodes().Get_Tail());
to->Get_In_Nodes().insert_after(from, to->Get_In_Nodes().Get_Tail());
}