I have two classes: "node" and "poly". The node objects are linked together to form a linked list. The poly object holds a pointer to the first node. I am trying to deallocate the memory for the entire "poly". I want to delete the poly - then within the poly destructor call a function (something like "freePoly") that will help me iterate through the entire linked list of node objects - deleting all nodes.
Here is the class definition:
class Node
{
private:
double coeff;
int exponent;
Node *next;
public:
Node(double c, int e, Node *nodeobjectPtr)
{
coeff = c;
exponent = e;
next = nodeobjectPtr;
}
~Node()
{
printf("Node Destroyed");
//???
}
class poly
{
private:
Node *start;
public:
poly(Node *head) /*constructor function*/
{
start = head;
}
~poly() /*destructor*/
{
//???
}
void freePoly();
};
void poly::freePoly()
{
//???
}
I've tried a lot of things, but essentially I get stuck where I'm only deleting the first node object. Then I've lost the pointer to the other nodes... and leak memory because I can't access them anymore for deletion.
You can avoid a lot of problems and work by using a std::vector instead of a Do-It-Yourself linked list. Unless this is for learning.
That said, do
~poly() /*destructor*/
{
while( start != 0 )
{
node* p_doomed = start;
start = start->next;
delete p_doomed;
}
}
There are also many other ways to do this, but the above is a pattern that can help you figure out how to do similar things.
If you want to keep your code as is, then your freePoly should look like this:
while(start)
{
Node *ptr = start;
start = start->getNext();
delete ptr;
}
Notice what this code does: first it makes a copy of the pointer to the current head - i.e. the first Node, then it makes head point to the next object and only then calls delete for the old head pointer.
Of course, this design isn't ideal: you are programming using a C++ compiler and you have some classes and some member functions but you aren't really using C++ effectively:
Not only does language provides you with wonderful tools such as std::list or std::vector so that you don't have to reinvent the wheel and things like std::unique_ptr so that pointers know when it's safe to delete themselves.
It also provides you with powerful abstract concepts to model the bahavior of objects.
I suggest that you take a step back and rethink your code. Key questions to ask are: how can I write less code here? What facilities of C++ can I leverage here? What are these objects I have and what does each object do?
I understand that this may be a homework exercise and you have to implement things a certain way, but don't let that stop you from learning.
You could try this:
private:
void auxDestroy(Node* p);
void Node::auxDestroy(Node* p){
if (p!=0) {
if (p->next != 0) {
auxDestroy(p->next);
}
else {
delete p;
}
}
}
Then in the destroy method you could call this auxDestroy(this->next);
~Node(){
auxDestroy(this->next);
}
And in poly destructor:
~poly(){
delete this->start;
}
Related
How to deal with memory leaking with template classes in C++?
In this code I defined 4 template classes:
class node and class linked_list make up a doubly linked list
class item and class bag just make up another doubly linked list
These template classes are designed to deal with objects of various classes.
In the main function, I first created a linked_list<string> and a bag<int> and everything is fine.
But when I try to make a bag<linked_list<string>>, problems arise.
I tried to trace back to see what happened, and I saw that in the function push_back in class bag, a destructor of linked_list has been called that erased all the data in the input v. I don't know why that happens.
Note that I overwrote the destructors for all classes and called className.~className() in the main function to prevent memory leaking.
And it does work to prevent memory leaking from ls_1 and bag_1.
I don't know which part of my code is wrong. Can somebody help me?
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
//node and linked_list class make up a doubly linked list
template<class T> class node {
public:
T value;
node<T> * next;
node<T> * previous;
node<T>() { next = nullptr; previous = nullptr; }
node<T>(T v) { value = v; next = nullptr; previous = nullptr; }
~node<T>() { delete next; }
};
template<class T> class linked_list { //doubly linked list
public:
node<T> * head;
node<T> * tail;
linked_list<T>() { head = nullptr; tail = nullptr; }
~linked_list<T>() { delete head; }
void push_front(T v) { //insert an item to the front
node<T> * p = new node<T>(v);
p->next = head;
head = p;
if (tail == nullptr) {
tail = p;
}
}
};
//item and bag class just make up another doubly linked list
template<class X> class item {
public:
X value;
item<X> *next;
item<X> *previous;
item<X>(X v) { value = v; next = nullptr; previous = nullptr; }
~item<X>() { delete next; }
};
template<class X> class bag { //just another doubly linked list
public:
item<X> *last;
item<X> *first;
int num_items;
int size() { return num_items; }
bag() { last = nullptr; first = nullptr; num_items = 0; }
~bag() { delete first; }
void push_back(X v) { //insert an item to the back
item<X> * p = new item<X>(v);
if (num_items == 0) {
last = first = p;
}
else {
last->next = p;
p->previous = last;
last = p;
}
num_items++;
last->next = nullptr;
}
};
int main() {
//When using built-in classes (like strings) as input
//there's no problem at all
linked_list<string> ls_1;
ls_1.push_front("David");
ls_1.push_front("John");
bag<int> bag_1;
bag_1.push_back(1);
bag_1.push_back(2);
//Problems arise here when using user defined classes (linked_list) as input
//I traced back and found out that a destructor has been called
//that erases all the data in the input. Donno how that happens
bag<linked_list<string>> bag_string;
bag_string.push_back(ls_1);
//These lines are to prevent the memory leaking
//I overwrote destructors for linked_list and node class
//otherwise there's still memory leaking
ls_1.~linked_list();
bag_1.~bag();
bag_string.~bag();
_CrtDumpMemoryLeaks();
getchar();
getchar();
}
Implement node, linked_list, item, bag copy constructors and assignments or declare them as deleted. The default versions generated by the compiler do not do the deep copying and that leads to multiple deletes of same objects after they were copied.
Read the rule of three/five/zero for full details.
A bit off-topic, but making a list node delete its siblings is a classic gotcha: for a sufficiently long list it ends up calling ~node<T>() recursively until it exhausts the stack. And this is the reason node pointers cannot be smart-pointers.
A fix would be to have a default destructor for nodes and make the list destroy the nodes in a loop, rather than recursively.
You may also like to use the full list node as a head of the list that points to itself when empty. That removes that nullptr checking logic completely.
I tried to trace back to see what happened, and I saw that in the function push_back in class bag, a destructor of linked_list has been called that erased all the data in the input v
Yes, this happens because your bag::push_back() takes its argument by value. This means it creates a copy of the ls_1 you created in main. You have not specified how to "copy" a list, so the compiler generated this function (a copy constructor) automatically. It can do that because your linked_list only contains two pointers, so the compiler assumes (because you have not told it otherwise) that copying the pointers over is all that is necessary to generate a copy of a linked_list. Unfortunately, that is not correct.
You now have two lists that manage the same contents: The original ls_1 in main() and the function argument v in push_back() - they both contain the same pointers.
Then the same thing happens again in your item constructor: You make a local copy of the list that holds the same pointers as the first two.
You now have several list objects pointing to the same data. Each one will try to destroy the data once it dies. This results in undefined behavior.
To correct this, you need to figure out how copying of a list should work. This is (in part) what the rule linked in the other comment is about: If the destructor of your class is not trivial (i.e. the compiler-generated version would not be sufficient, most likely because you need to release a resource like allocated memory), you should/must always care about how to handle your class being copied around. The various mechanisms that may invoke copy-like behavior (assignment, copy constructor, plus move versions in newer C++) need to be specified (or forbidden) by you.
now i have been making games for a few years using the gm:s engine(tho i assure you i aint some newbie who uses drag and drop, as is all to often the case), and i have decided to start to learn to use c++ on its own, you know expand my knowledge and all that good stuff =D
while doing this, i have been attempting to make a list class as a practice project, you know, have a set of nodes linked together, then loop threw those nodes to get a value at a index, well here is my code, and i ask as the code has a single major issue that i struggle to understand
template<class type>
class ListNode
{
public:
type content;
ListNode<type>* next;
ListNode<type>* prev;
ListNode(type content) : content(content), next(NULL), prev(NULL) {}
protected:
private:
};
template<class type>
class List
{
public:
List() : SIZE(0), start(NULL), last(NULL) {}
unsigned int Add(type value)
{
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
else
{
ListNode<type> a(value);
this->last->next = &a;
a.prev = this->last;
this->last = &a;
}
this->SIZE++;
return (this->SIZE - 1);
}
type Find(unsigned int pos)
{
ListNode<type>* a = this->start;
for(unsigned int i = 0; i<this->SIZE; i++)
{
if (i < pos)
{
a = a->next;
continue;
}
else
{
return (*a).content;
}
continue;
}
}
protected:
private:
unsigned int SIZE;
ListNode<type>* start;
ListNode<type>* last;
};
regardless, to me at least, this code looks fine, and it works in that i am able to create a new list without crashing, as well as being able to add elements to this list with it returning the proper index of those elements from within the list, however, beyond that the problem arises when getting the value of a element from the list itself, as when i ran the following test code, it didn't give me what it was built to give me
List<int> a;
unsigned int b = a.Add(313);
unsigned int c = a.Add(433);
print<unsigned int>(b);
print<int>(a.Find(b));
print<unsigned int>(c);
print<int>(a.Find(c));
now this code i expected to give me
0
313
1
433
as that's what is been told to do, however, it only half does this, giving me
0
2686684
1
2686584
now, this i am at a lost, i assume that the values provided are some kind of pointer address, but i simply don't understand what those are meant to be for, or what is causing the value to become that, or why
hence i ask the internet, wtf is causing these values to be given, as i am quite confused at this point
my apologies if that was a tad long and rambling, i tend to write such things often =D
thanks =D
You have lots of undefined behaviors in your code, when you store pointers to local variables and later dereference those pointers. Local variables are destructed once the scope they were declared in ends.
Example:
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
Once the closing brace is reached the scope of the if body ends, and the variable a is destructed. The pointer to this variable is now a so called stray pointer and using it in any way will lead to undefined behavior.
The solution is to allocate the objects dynamically using new:
auto* a = new ListNode<type>(value);
Or if you don't have a C++11 capable compiler
ListNode<type>* a = new ListNode<type>(value);
First suggestion: use valgrind or a similar memory checker to execute this program. You will probably find there are many memory errors caused by dereferencing stack pointers that are out of scope.
Second suggestion: learn about the difference between objects on the stack and objects on the heap. (Hint: you want to use heap objects here.)
Third suggestion: learn about the concept of "ownership" of pointers. Usually you want to be very clear which pointer variable should be used to delete an object. The best way to do this is to use the std::unique_ptr smart pointer. For example, you could decide that each ListNode is owned by its predecessor:
std::unique_ptr<ListNode<type>> next;
ListNode<type>* prev;
and that the List container owns the head node of the list
std::unique_ptr<ListNode<type>> start;
ListNode<type>* last;
This way the compiler will do a lot of your work for you at compile-time, and you wont have to depend so much on using valgrind at runtime.
Hello I am trying to use pointers and learning the basics on unique pointers in C++. Below is my code I have commented the line of code in main function. to debug the problem However, I am unable to do so. What am I missing ? Is my move() in the insertNode() incorrect ? The error I get is below the code :
#include<memory>
#include<iostream>
struct node{
int data;
std::unique_ptr<node> next;
};
void print(std::unique_ptr<node>head){
while (head)
std::cout << head->data<<std::endl;
}
std::unique_ptr<node> insertNode(std::unique_ptr<node>head, int value){
node newNode;
newNode.data = value;
//head is empty
if (!head){
return std::make_unique<node>(newNode);
}
else{
//head points to an existing list
newNode.next = move(head->next);
return std::make_unique<node>(newNode);
}
}
auto main() -> int
{
//std::unique_ptr<node>head;
//for (int i = 1; i < 10; i++){
// //head = insertNode(head, i);
//}
}
ERROR
std::unique_ptr>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
Aside from other small problems, the main issue is this line:
return std::make_unique<node>(newNode);
You are trying to construct a unique pointer to a new node, passing newNode to the copy constructor of node. However, the copy constructor of node is deleted, since node contains a non-copyable type (i.e. std::unique_ptr<node>).
You should pass a std::move(newNode) instead, but this is problematic since you create the node on the stack and it will be destroyed at the exit from the function.
Using a std::unique_ptr here is a bad idea in my opinion, since, for example, to print the list (or insert into the list), you need to std::move the head (so you lose it) and so on. I think you're much better off with a std::shared_ptr.
I was having the same problem and indeed using a shared_ptr works.
Using the smart pointer as an argument in the function copies the pointer (not the data it points to), and this causes the unique_ptr to reset and delete the data it was previously pointing at- hence we get that "attempting to reference a deleted function" error. If you use a shared_ptr this will simply increment the reference count and de-increment it once you are out of the scope of that function.
The comments in the answers above suggest that using a shared_ptr is baseless. These answers were written before the C++17 standard and it is my understanding that we should be using the most updated versions of the language, hence the shared_ptr is appropriate here.
I don't know why we have to expose node type to user in any case. Whole thingamajig of C++ is to write more code in order to write less code later, as one of my tutors said.
We would like to encapsulate everything and leave no head or tail (pun intended) of node to user. Very simplistic interface would look like:
struct list
{
private:
struct node {
int data;
std::unique_ptr<node> next;
node(int data) : data{data}, next{nullptr} {}
};
std::unique_ptr<node> head;
public:
list() : head{nullptr} {};
void push(int data);
int pop();
~list(); // do we need this?
};
The implementation does something what Ben Voigt mentioned:
void list::push(int data)
{
auto temp{std::make_unique<node>(data)};
if(head)
{
temp->next = std::move(head);
head = std::move(temp);
} else
{
head = std::move(temp);
}
}
int list::pop()
{
if(head == nullptr) {
return 0; /* Return some default. */
/* Or do unthinkable things to user. Throw things at him or throw exception. */
}
auto temp = std::move(head);
head = std::move(temp->next);
return temp->data;
}
We actually need a destructor which would NOT be recursive if list will be really large. Our stack may explode because node's destructor would call unique_ptr's destructor then would call managed node's destructor, which would call unique_ptr's destructor... ad nauseatum.
void list::clear() { while(head) head = std::move(head->next); }
list::~list() { clear(); }
After that default destructor would ping unique_ptr destructor only once for head, no recursive iterations.
If we want to iterate through list without popping node, we'd use get() within some method designed to address that task.
Node *head = list.head.get();
/* ... */
head = head->next.get();
get() return raw pointer without breaking management.
How about this example, in addition to the sample code, he also mentioned some principles:
when you need to "assign" -- use std::move and when you need to just traverse, use get()
I have a class called "node". I link a bunch of node objects together to form a linked list. When the "node" destructor is called, it only deletes the first node. How do I iterate through the entire linked list of nodes and delete each node object?
Here is the class definition:
class Node
{
private:
double coeff;
int exponent;
Node *next;
public:
Node(double c, int e, Node *nodeobjectPtr)
{
coeff = c;
exponent = e;
next = nodeobjectPtr;
}
~Node()
{
printf("Node Destroyed");
}
The destructor is called by invoking delete on the pointer to the first node of the linked node list.
Since you don't know how many nodes there are in a list, if you do not have firm bounds on that it's not a good idea to invoke destructors recursively, because each call uses some stack space, and when available stack space is exhausted you get Undefined Behavior, like a crash.
So if you absolutely want to do deallocate following nodes in a node's destructor, then it has to first unlink each node before destroying it.
It can go like this:
Node* unlink( Node*& p )
{
Node* result = p;
p = p->next;
result->next = nullptr;
return result;
}
Node::~Node()
{
while( next != nullptr )
{
delete unlink( next );
}
}
But better, make a List object that has ownership of the nodes in a linked list.
Of course, unless this is for learning purposes or there is a really good reason to roll your own linked list, just use a std::vector (and yes I mean that, not std::list).
How do I iterate through the entire linked list of nodes and delete each node object?
It would be cleaner if you had a separate class to manage the entire list, so that nodes can be simple data structures. Then you just need a simple loop in the list's destructor:
while (head) {
Node * victim = head;
head = victim->next; // Careful: read this before deleting
delete victim;
}
If you really want to delegate list management to the nodes themselves, you'll need to be a bit more careful:
while (next) {
Node * victim = next;
next = victim->next;
victim->next = nullptr; // Careful: avoid recursion
delete victim;
}
Under this scheme, you'll also need to be careful when deleting a node after removing it from the list - again, make sure you reset its pointer so it doesn't delete the rest of the list. That's another reason to favour a separate "list" class.
I'm writing a program in python that uses genetic techniques to optimize expressions.
Constructing and evaluating the expression tree is the time consumer as it can happen
billions of times per run. So I thought I'd learn enough c++ to write it and then incorporate it
in python using cython or ctypes.
I've done some searching on stackoverflow and learned a lot.
This code compiles, but leaves the pointers dangling.
I tried this_node = new Node(... . It didn't seem to work. And I'm not at all sure how I'd
delete all the references as there would be hundreds.
I'd like to use variables that stay in scope, but maybe that's not the c++ way.
What is the c++ way?
class Node
{
public:
char *cargo;
int depth;
Node *left;
Node *right;
}
Node make_tree(int depth)
{
depth--;
if(depth <= 0)
{
Node tthis_node("value",depth,NULL,NULL);
return tthis_node;
}
else
{
Node this_node("operator" depth, &make_tree(depth), &make_tree(depth));
return this_node;
}
};
The Node object returned by make_tree() is just a temporary object, it will automatically be destroyed again at the end of the expression in which the function is called. When you create a pointer to such a temporary object, like in &make_tree(depth), this pointer will not point to anything useful anymore once the temporary object got destroyed.
You should use real dynamic memory allocation with new and delete to build the tree, so that you don't end up with pointers to not longer existing objects. Probably this construction of the tree should be done in a constructor of the Node class, the destructor should then take care of the deletes needed to release the used memory. For example:
class Node {
public:
const char *cargo;
int depth;
Node *left;
Node *right;
Node(int a_depth);
~Node();
};
// constructor
Node::Node(int a_depth) {
depth = a_depth;
a_depth--;
if(a_depth <= 0)
{
cargo = "value";
left = NULL;
right = NULL;
}
else
{
cargo = "operator";
left = new Node(a_depth);
right = new Node(a_depth);
}
}
// destructor
Node::~Node() {
delete left;
delete right;
}
The C++ way would be to use smart pointers.
Here you're returning copies of local objects, making temporary objects. Once the make_node call is finished the object don't exist anymore making your pointers dangling.
So don't do that.
Use smart pointers instead to allow the nodes to be freed once unreferenced.