I have this code from an old exam, which I want fix from its faults. Everytime I call insertlast/insertfirst I allocate new memory for my list which I can't seem to free. I have run it with valgrind and gets a new leak everytime i call insertfirst/insertlast. Valgrind also complains on my loop where I try to free the memory. I get something like this:
Invalid free() / delete / delete[] / realloc()
==4548== at 0x4C2C2BC: operator delete(void*)(in/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4548== by 0x4007D6: main (code6.cpp:67)
==4548== Address 0xffefffea0 is on thread 1's stack
Here's the code:
#include <iostream>
using namespace std;
template <class T>
struct Node {
Node() : data(T()), next(nullptr) {}
Node(T d, Node * p) : data(d), next(p) {}
T data;
Node<T> * next;
};
template <class T>
void insertlast (Node<T> * p, T data) {
if (p == nullptr) {
p = new Node<T>(data, nullptr);
} else {
while (p -> next != nullptr) {
p = p -> next;
}
p -> next = new Node<T>(data, nullptr);
}
}
template <class T>
void insertfirst (Node<T> * & p, const T & data) {
Node<T> * tmp = new Node<T>(data, p);
p = tmp;
}
template <class T>
void printNode(Node<T> *& node) {
cout << node->data << " -> ";
while (node->next != nullptr) {
node = node->next;
cout << node->data << " -> ";
}
cout << endl;
}
template <class T>
void printNode2(Node<T> & node) {
cout << node.data << " -> ";
while (node.next != nullptr) {
node = *node.next;
cout << node.data << " -> ";
}
cout << endl;
}
int main() {
Node<int> node;
Node<int> * temp = &node;
Node<int> * ref = &node;
insertlast(ref, 5);
insertfirst(ref, 3);
insertlast(ref, 6);
insertfirst(ref, 2);
//printNode(ref);
//printNode2(node);
while(ref->next != nullptr){
temp = ref->next;
delete ref;
ref = temp;
}
return 0;
}
It would be cool if you could help me out to find out what's wrong with the code. My guess is that it's something fishy with the pointer reference in insertfirst, but I can't figure it out.
Thanks in advance!
When you call insertfirst the first time, you will create a new node whose next pointer is the statically allocated node object from main, then when you loop over the list to delete the nodes in it, you will try to delete this node object.
What you should do, if you want a sentinel object at the head of the list, is to make its next pointer point to the new node, and the new node should have its next pointer set to p->next. So something like
template <class T>
void insertfirst (Node<T> * head, const T & data) {
Node<T> * tmp = new Node<T>(data, head->next);
head->next = tmp;
}
Finally a hint on how to debug these things: Draw it on paper! After every operation, draw it out on paper, and problems like this would have been very easy to spot.
In your insertlast function, if the argument p is NULL, then your code will leak an instance of Node. You create the new instance and assign its address to p, but once you leave the function, p goes out of scope and you no longer have a pointer to the newly created instance.
I suppose you wanted to pass a reference to p like in your insertfirst function, but forgot to put the & char in there.
There is inconsistent interface of these two functions
template <class T>
void insertlast (Node<T> * p, T data) {
if (p == nullptr) {
p = new Node<T>(data, nullptr);
} else {
while (p -> next != nullptr) {
p = p -> next;
}
p -> next = new Node<T>(data, nullptr);
}
}
template <class T>
void insertfirst (Node<T> * & p, const T & data) {
Node<T> * tmp = new Node<T>(data, p);
p = tmp;
}
In the first function parameters are declared like Node<T> * p, T data while in the second function they are declared like Node<T> * & p, const T & data
In the first function you also shall pass the first parameter by reference. Otherwise p is a local variable of the function and changes of it will not influence to the original argument.
In can be defined the following way
template <class T>
void insertlast ( Node<T> * &p, const T &data )
{
if ( p == nullptr )
{
p = new Node<T>(data, nullptr);
}
else
{
Node<T> *tmp = p;
while ( tmp->next != nullptr )
{
tmp = tmp->next;
}
tmp->next = new Node<T>( data, nullptr );
}
}
Also you have to initialize the first node in main to nullptr
Node<int> *node = nullptr;
It is a bad idea to define the first node of the list in the stack. It is simply an invalid design.
Related
i'm trying to make a template class for a list in c++. This is something new for me, and i'm stuck. I've written add(T item) method and write() to write whole list on console, but i have random int as output.
Here's my code, if someone could tell me where my mistake is, i will be grateful.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
template <class T> class Node {
private:
Node<T> * next;
Node<T> * prev;
T key;
public:
Node(T k) {
next =(Node *) malloc(sizeof(Node));
prev = (Node *)malloc(sizeof(Node));
key = k;
}
Node(T * n, T * p, T k) {
next = n;
prev = p;
key = k;
}
void setNext(Node<T> * n) {
next = n;
}
void setPrev(Node<T> * p) {
prev = p;
}
void show() {
cout << "key= " << key << endl;
}
};
template <class T> class List {
private:
Node<T> * head;
Node<T> * tail;
public:
List() {
head = nullptr;
tail = nullptr;
cout << "list created!" << endl;
}
void add(T item) {
Node<T> node(item);
node.setNext(head);
node.setPrev(nullptr);
if (head != nullptr)
head = &node;
else {
tail = &node;
}
head = &node;
}
void write() {
head->show();
}
};
int main()
{
List<int> lista;
lista.add(8);
lista.write();
return 0;
}
Your add() add a pointer to a Note<T> (node) in the list; but node is destroied when add() ends the execution.
So, when you call write(), that use show(), the pointed memory in undefined (random value).
To avoid this problem, you have to allocate the variable (with new! avoid malloc() with classes), so
Node<T> * nodePnt = new Node<T>(item);
and
head = nodePnt;
tail = nodePnt;
But remeber to delete it.
I tried to search the topic but all the threads I found used while loops.
However I would like to do this recursively:
template <typename S>
struct node {
S data;
node<S> * next;
};
this is the function I invoke in the destructor (pass the head as parameter) of the linked list:
void destroy(node<T> * n) {
if(n->next != NULL){
destroy(n->next);
}
delete n;
}
Unfortunately the result is a segmentation fault.
Can someone help me?
Edit: complete code
#include <iostream>
using namespace std;
template <typename T>
class List {
private:
template <typename S>
struct node {
S data;
node<S> * next;
};
node<T> * first;
node<T> * get_last_p() {
if(first != NULL){
return get_last(first);
}
return NULL;
}
node<T> * get_last(node<T> * n) {
if(n->next != NULL) {
return get_last(n->next);
} else {
return n;
}
return NULL;
}
void destroy(node<T> * n) {
if(n->next != NULL){
destroy(n->next);
}
delete n;
}
public:
List() {first->next = 0;}
~List() {destroy(first);}
void add(T element) {
node<T> * new_element = new node<T>;
new_element->data = element;
if(first == NULL){
first = new_element;
} else {
get_last_p()->next = new_element;
}
}
T get_last() {
return get_last_p()->data;
}
T get_first() {
return first->data;
}
};
From what I can see, in List's constructor, first is not initialized, and is then immediately accessed. That is undefined behavior.
Even if first was somehow initialized to null in an unreliable way, and that first->next = 0; wouldn't crash somehow, you'd also fail in your destructor's destroy, since destroy assumes its original argument is not null.
I assume you meant to
List() : first{ new node{} } { first->next = nullptr; }
If first is not meant to hold a value, then you're going to have to refactor your code to first initialize first to null - there's no working around that - and handle the case where first is null explicitely in all your code. You cannot assign first->next of a null, invalid or undefined pointer.
Compiler says segmentation fault but doesn't tell me which line. From what I understand, a segmentation fault usually means a value at address NULL was attempted to be accessed, but I do not see where that's happening.
#include <iostream>
template <typename T> class SinglyLinkedList
{
struct node
{
T val;
node * next;
};
public:
SinglyLinkedList ();
SinglyLinkedList (T *, size_t);
~SinglyLinkedList ();
void push_back (T);
void print ();
private:
node * _root;
};
int main ()
{
int myArray [] = { 1, 69, -23942, 11111 };
SinglyLinkedList<int> myList(myArray, sizeof(myArray)/sizeof(int));
myList.print();
return 0;
}
template <typename T> SinglyLinkedList<T>::SinglyLinkedList ( )
{
_root = NULL;
}
template <typename T> SinglyLinkedList<T>::SinglyLinkedList (T * arr, size_t n)
{
/* Initialize a singly-linked list of objects of type T from an array of objects of type T */
if (n > 0)
{
node * lastNode = new node;
lastNode->val = *arr;
lastNode->next = NULL;
for (T * pa(arr+1), * pb(arr+n); pa != pb; ++pa)
{
node * thisNode = new node;
thisNode->val = *pa;
thisNode->next = NULL;
lastNode->next = thisNode;
lastNode = thisNode;
}
delete lastNode;
}
else
{
_root = NULL;
}
}
template <typename T> SinglyLinkedList<T>::~SinglyLinkedList ( )
{
node * thisNode = _root;
while (thisNode != NULL)
{
node * temp = thisNode;
thisNode = thisNode->next;
delete temp;
}
}
template <typename T> void SinglyLinkedList<T>::print ( )
{
if (_root == NULL) return;
for (node * thisNode = _root; thisNode != NULL; thisNode = thisNode->next)
{
std::cout << thisNode->val << "->";
}
std::cout << "NULL";
}
Your constructor is wrong.
If n>0 (as in this case) you do a lot of pointer-pointing (which doesn't do what you think it does), but assign no value to _root. Then in print() you dereference _root, which does not point to a valid object; you're lucky all you get is a seg fault.
I'm trying to implement a linked list class in C++ and I got problem. I have the += operator who adds new node.
the linked list class interface:
template <typename Type>
class LinkedList {
public:
LinkedList<Type>* head;
// linked list stracture
Type data;
LinkedList<Type>* next;
// others ....
size_t length;
public:
LinkedList();
~LinkedList();
void initializeHead(LinkedList<Type>* headPtr);
size_t size() const;
LinkedList& operator+=(const Type& add);
void operator-=(const Type& remove);
LinkedList<Type>& operator[] (const size_t index) const;
bool operator== (const LinkedList<Type> &versus) const;
friend ostream& operator<< (ostream& out,LinkedList& obj);
};
and here i have the += overload implement:
template <typename Type> LinkedList<Type>& LinkedList<Type>::operator +=(const Type& add) {
// head ptr - :)
LinkedList<Type>* p = head->next;
// go to the end
while(p) p = p->next;
// now on end - create new..!!!
try {
p = new LinkedList<Type>;
} catch (bad_alloc& e) {
cout << "There\'s an allocation error....";
} catch (...) {
cout << "An unknown error.." << endl;
}// fill and done
p->data = add;
p->next = NULL;
// increment length .........
++head->length;
// done ............
return *p;
}
Additionally , I have "array" access overload method:
template <typename Type> LinkedList<Type>& LinkedList<Type>::operator [](const size_t index) const {
if(index < 0 || index >= length) // invaild argument
throw exception();
// continue
LinkedList<Type>* p = head;
for(size_t i = 0; i < index; ++i) p = p->next; // we are at what we want
return *p;
}
All works correctly - I checked on the dibugger,
the problem is - += doesn't save the new node in "head->next", for some reason, after finish += method, head->next equal to null.
Do someone know why the new allocation don't link to head->next?
Thanks a lot!!
after while(p) p = p->next; p is NULL
and next you do p = new LinkedList<Type>; but you don't link the p into the head.
Instead of:
// go to the end
while(p) p = p->next;
You need:
head->next = p;
As the other answers say, you go beyond the list when you try to add. Try something like this:
template <typename Type> LinkedList<Type>& LinkedList<Type>::operator +=(const Type& add)
{
LinkedList<Type> *last;
// Find the last node in the list
for (last = head; last != 0 && last->next != 0; last = last->next)
{
}
// `last` now points to the last node in the list, or is zero
// If zero (i.e. NULL) then list is empty
if (last == 0)
{
head = new LinkedList<Type>;
head->next = 0;
head->data = add;
head->length = 0;
}
else
{
last->next = new LinkedList<Type>;
last->next->next = 0;
last->next->data = add;
}
// We can safely use `head` as we are sure it won't be zero
head->length++;
// Return the added node
return (last != 0 ? *last->next : *head);
}
You can also use temporary variable to store last node and then the last node will point to new node.
This is sample code. You need to take care of some situations like adding first node etc.
LinkedList<Type>* temp = NULL;
while(p)
{
temp = p;
p = p->next;
}
try
{
p = new LinkedList<Type>;
temp->next = p;
}
I am writing a linked list template class in C++ as an exercise for myself to help me get back into C++ programming. I've got the following class definition:
template <typename T>
class List
{
public:
List();
~List();
void append(T data);
void display();
int count();
private:
struct Node
{
T data;
Node *next;
} *head;
};
I have two versions of the append method - one that works and one that doesn't. I can't figure out what the difference, in terms of the operations performed, is, and why the second one doesn't work. Here's the one that works:
template <typename T>
void List<T>::append(T data)
{
if (head == NULL)
{
head = new Node;
head->data = data;
head->next = NULL;
}
else
{
Node *p = head, *q;
while (p != NULL)
{
q = p;
p = p->next;
}
p = new Node;
p->data = data;
p->next = NULL;
q->next = p;
}
}
And here's the one that doesn't seem to actually add any elements to the list:
template <typename T>
void List<T>::append(T data)
{
Node *p = head, *q = head;
while (p != NULL)
{
q = p;
p = p->next;
}
p = new Node;
p->data = data;
p->next = NULL;
if (q != NULL)
{
q->next = p;
}
}
Any ideas as to why the second version doesn't add any elements? I've been trying it with type T as int.
P.S. Neither version gives any errors or warnings during compilation, nor during runtime.
The second method only handles the case where the list is non-empty.
When the list is empty, the line q->next = p; is never reached, so the new element is leaked with no pointer existing to it after p goes out of scope.
What you want, if you would like to eliminate the special case for empty list, is a Node **, like thus:
template <typename T>
void List<T>::append(T data)
{
Node** q = &head; /* head acts as the first Node::next link */
/* invariant: q points to some Node::next field (or head, which acts like one) */
while (*q)
q = &(*q)->next;
/* invariant: q points to the Node::next field at the end of the chain, which is currently NULL */
*q = new Node { data, nullptr };
}
In the first version you change the head, in the second - you don't.
Simpler would be:
template <typename T>
void List<T>::append(T data)
{
p = new Node;
p->data = data;
p->next = head;
head = p;
}
That would also be more logical because entering an item to a linked list shouldn't take O(n) as it does for you...
If you absolutely have to add to the end, do this:
template <typename T>
void List<T>::append(T data)
{
p = new Node;
p->data = data;
p->next = NULL;
if (tail)
tail->next = p;
else // first time
tail = head = p;
}