I have implemented a singly-linked-list where there is a SinglyList class, and struct node, node *head as private members of the class; and wrote a destructor to delete it. I used CRT library to check for memory leaks using _CrtDumpMemoryLeaks() method. When I debug the code, it shows in the debug console that memory leaks are found, which is strange since I wrote a destructor to delete it.
This is shown in the debug console:-
Here is the node class:-
struct node
{
int data = NULL;
node*next = NULL;
};
Here is the destructor:-
SinglyList::~SinglyList()
{
node*curr = head,*next;
while(curr != NULL)
{
next = curr->next;
delete curr;
curr = next;
}
}
I don't understand, how can there be memory leaks when all nodes are deleted, kindly help.
Edit:
SinglyList.hpp:-
#pragma once
#include<iostream>
class SinglyList
{
private:
struct node
{
int data = NULL;
node*next = NULL;
};
node*head;
public:
SinglyList();
void Append(const int&);
void Prepend(const int&);
void Print();
void Insert(const int&,const int&);
void Delete(const int&);
void Reverse();
bool isEmpty();
~SinglyList();
};
SinglyList::SinglyList()
{
head = NULL;
}
SinglyList::~SinglyList()
{
node*curr = head,*next;
while(curr != NULL)
{
next = curr->next;
delete curr;
curr = next;
}
}
void SinglyList::Append(const int&data)
{
node*n = new node{data};
if(!head)
{
head = n;
return;
}
node*ptr = head;
while(ptr->next)
ptr = ptr->next;
ptr->next = n;
}
void SinglyList::Prepend(const int&data)
{
node*n = new node{data};
if(!head)
{
head = n;
return;
}
n->next = head;
head = n;
}
void SinglyList::Print()
{
if(!head)
return;
node*ptr = head;
while(ptr)
{
std::cout<<ptr->data<<' ';
ptr = ptr->next;
}
std::cout<<std::endl;
}
void SinglyList::Insert(const int&pos,const int&data)
{
if(pos == 1)
{
Prepend(data);
return;
}
node*n = new node{data};
node*ptr = head;
for(int i = 1;i!=pos-1;i++)
ptr = ptr->next;
n->next = ptr->next;
ptr->next = n;
}
void SinglyList::Delete(const int&pos)
{
if(!head)
return;
node*ptr = head;
if(pos == 1)
{
head= head->next;
delete ptr;
return;
}
for(int i = 1;i!= pos-1;i++)
ptr = ptr->next;
node*temp = ptr->next;
ptr->next = temp->next;
delete temp;
}
void SinglyList::Reverse()
{
if(!head)
return;
node*curr = head,*prev = NULL,*next = NULL;
while(curr)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
}
bool SinglyList::isEmpty()
{
return (!head);
}
main.cpp:-
#include"SinglyList.hpp"
#include<crtdbg.h>
int main()
{
SinglyList nums{};
nums.Append(10);
nums.Append(20);
nums.Append(30);
_CrtDumpMemoryLeaks();
return 0;
}
You print the leaks before the list gets deleted. Try this instead:
#include"SinglyList.hpp"
#include<crtdbg.h>
int main()
{
{
SinglyList nums{};
nums.Append(10);
nums.Append(20);
nums.Append(30);
}
_CrtDumpMemoryLeaks();
return 0;
}
Then, you'll show the actual leaks after your list gets destroyed.
Related
I have made a linked list with c++.
I have no idea when trying to point to the next element of the list, the program stops.
My Node Class as follows:
class Node {
friend class List;
private :
Node* next;
public:
int value;
Node()
{
value = 0;
next = nullptr;
}
Node(int data)
{
this->value = data;
this->next = nullptr;
}
};
My List class has next and delete methods. Whenever there is calling for the next attributes in the Node class. The program stucks.
For my List Class I made them as follows:
class List {
private:
Node* head;
public:
List ()
{
head = 0; // create an empty list
}
~List ()
{
delete head; // clean up the list and all nodes
}
Node* first () const
{
return head;
}
Node* next(const Node* n) const{
return n->next;
}
void append(int i)
{
Node* newNode = new Node(i);
if (head == nullptr){
head = newNode;
}
else
{
Node *ptr = head;
// the loop sets ptr to last node of the linked list
while (ptr->next != nullptr){
ptr = ptr->next;
}
// ptr now points to the last node
// store temp address in the next of ptr
ptr->next = newNode;
}
}
void insert(Node* n, int i)
{
Node *ptr = head;
Node *newNode = new Node(i);
newNode->next = n;
if(n==head)
{
head = newNode;
}
else
{
while(ptr->next != n)
{
ptr = ptr->next;
}
ptr->next = newNode;
}
}
void erase( Node* n)
{
Node *ptr = head;
Node *before ;
if (n->next == nullptr)
{
free(n);
return ;
}
if(head == n)
{
head = n->next;
free(n);
return ;
}
else
{
while(ptr!= n)
{
before = ptr;
ptr = ptr->next ;
}
before->next = ptr;
free(ptr);
free(n);
return ;
}
}
void printLst()
{
while(head != nullptr)
{
std::cout<<head->value<<" ";
head = head->next;
}
}
};
and to get a full vision of program. I made the main function very simple:
int main()
{
List list;
list.append(55);
list.append(50);
list.append(20);
list.append(30);
list.insert(list.first(), 22);
list.insert(list.first(), 87);
list.printLst();
list.erase(list.first());
list.printLst();
}
Any suggestions ?
in erase you never assign a value to 'before'
Node* before;
then you do
before->next = ptr;
Error C4703 potentially uninitialized local pointer variable 'before' used ConsoleApplication1 C:\work\ConsoleApplication1\ConsoleApplication1.cpp 124
also - more importantly your printLst function sets head to null
void printLst()
{
while (head != nullptr)
{
std::cout << head->value << " ";
head = head->next; <<========
}
}
your print function should not change head
so list.first then returns null so this
list.erase(list.first());
calls erase with null
Exception thrown: read access violation.
n was nullptr.
I am trying to delete a node from the end of the doubly linked list,but i am getting:
segmentation fault
i have added different functions to add the node, from beginning , from end , and at any position.I checked the insertion of nodes,its working fine,the DLL is displayed correctly,but when it comes to deleting function,it gives segmentation fault.
struct Node {
Node* left;
Node* right;
int data;
};
Node* head = NULL;
void insertion_At_End(int element) {
Node* ptr = head;
Node* temp = new Node;
temp->left = temp->right = NULL;
temp->data = element;
if(head==NULL) {
head = temp;
} else {
while(ptr->right!=NULL) {
ptr = ptr->right;
}
temp->left = ptr->right;
ptr->right = temp;
}
}
void insertion_At_Beg(int element) {
Node* ptr = head;
Node* temp = new Node;
temp->left = temp->right = NULL;
temp->data = element;
if(head==NULL) {
head = temp;
} else {
temp->right = ptr;
ptr->left = temp;
head = temp;
}
}
void insertion_At_Pos(int element , int position , int length) {
Node* ptr;
Node* temp = new Node;
temp->left = temp->right = NULL;
temp->data = element;
int counter = 1;
if(position==1) {
insertion_At_Beg(element);
}
else if(position==length) {
insertion_At_End(element);
}
else {
ptr = head;
while(counter!=(position-1)) {
ptr = ptr->right;
counter++;
}
temp->right = ptr->right;
ptr->right->left = temp;
temp->left = ptr;
ptr->right = temp;
}
}
void deletion_At_End() {
Node *ptr = head;
while(ptr->right!=NULL) {
ptr = ptr->right;
}
ptr->left->right=NULL;
delete ptr;
}
I get the error if i have only one element in the list. When you have only one element in the list you can not set what it is in its left's right pointing to NULL because it does not exist! This works for me:
void deletion_At_End() {
Node *ptr = head;
while(ptr->right!=NULL) {
ptr = ptr->right;
}
if(ptr->left == NULL){
delete ptr;
}
else{
ptr->left->right=NULL;
delete ptr;
}
}
#include <iostream>
using namespace std;
class List {
public:
struct node {
int data;
node *next;
};
node* head = NULL;
node* tail = NULL;
node* temp = NULL;
node* prev = NULL;
public:
void addNum(int num) {
temp = new node;
temp->data = num;
temp->next = NULL;
if (head == NULL) {
head = temp;
tail = temp;
}
else {
tail->next = temp;
tail = temp;
}
}
void PrintList() {
temp = head;
while (temp != NULL) {
cout << temp->data << endl;
temp = temp->next;
}
}
void DelNum(int num) {
temp = head;
while (temp != NULL) {
if (temp->data == num) {
prev->next = temp->next;
free(temp);
}
temp = prev;
temp = temp->next;
}
}
};
int main() {
List list;
list.addNum(1);
list.addNum(2);
list.addNum(3);
list.addNum(4);
list.addNum(5);
list.addNum(6);
list.DelNum(3);
list.PrintList();
return 0;
}
What is wrong with my DelNum function? When I run the program nothing pops up. Doesn't matter what number I put in.
As mss pointed out the problem is in your DelNum() function where you assign temp = prev;. In your initialization you defined that node* prev = NULL; So, prev = NULL at the point when you assigned it to temp which caused segmentation fault when you try to use it like temp = temp->next;.
Two main problems are there in DelNum function:
first, when you are in while loop
, you should assign
prev = temp;
second, when you have found your target element, after deleting it you have to break out of the loop, which isn't done in your code
below is your corrected code( also correction of some other corner case in DelNum function ):
#include <iostream>
using namespace std;
class List {
public:
struct node {
int data;
node *next;
};
node* head = NULL;
node* tail = NULL;
node* temp = NULL;
node* prev = NULL;
public:
void addNum(int num) {
temp = new node;
temp->data = num;
temp->next = NULL;
if (head == NULL) {
head = temp;
tail = temp;
}
else {
tail->next = temp;
tail = temp;
}
cout<<num<<" is added \n";
}
void PrintList() {
temp = head;
while (temp != NULL) {
cout << temp->data << endl;
temp = temp->next;
}
}
void DelNum(int num) {
if(head==NULL)//empty
{
cout<<"empty linked list, can't be deleted\n";
return;
}
if(head->next==NULL)//means only one element is left
{
if(head->data==num)
{
node * fordelete=head;
head=NULL;
cout<<num<<"is deleted\n";
delete(fordelete);
}
else
{
cout<<"not found , can't be deleted\n";
}
return;
}
temp = head; // when more than one element are there
prev = temp;
while (temp != NULL) {
if (temp->data == num) {
prev->next = temp->next;
free(temp);
cout<<num<<" is deleted\n";
break;
}
prev= temp;
temp = temp->next;
}
if(temp==NULL)
{
cout<<"not found, can't be deleted\n";
}
}
};
int main() {
List list;
list.addNum(1);
list.addNum(2);
list.addNum(3);
list.addNum(4);
list.addNum(5);
list.addNum(6);
list.PrintList();
list.DelNum(3);
list.DelNum(7);
list.PrintList();
return 0;
}
I hope it will help you.
`Hello
I just wrote this code in Code Blocks and after building and running , it says that the programm has stopped working. I can't find what I have done wrong. I don't know if the problem is related to my code or is something that has to do with the compiler I am using or something else.
Please help
Library.h:
#ifndef LIBRARY_H
#define LIBRARY_H
#include <iostream>
#include <string>
using namespace std;
class Library
{
public:
struct book
{
string tittle;
int number;
struct book* next;
}* head, *tail, *ptr;
Library();
~Library();
book* searchName(book *, string);
void addNode(book *);
book *initNode(string s, int i);
void displayNode(book *ptr) const;
void displayList(book *ptr) const;
protected:
};
#endif
Library.cpp
#include "Library.h"
Library::Library() :
head(NULL), tail(NULL)
{
}
Library::~Library()
{
book *current, *temp;
current = head;
temp = head;
while (current != NULL)
{
current = current->next;
delete temp;
temp = current;
}
}
Library::book * Library::searchName(Library::book* ptr, string name)
{
while (name != ptr->tittle)
{
ptr = ptr->next;
if (ptr == NULL)
break;
}
return ptr;
}
void Library::addNode(book *newNode)
{
if (head == NULL)
{
head = newNode;
head = newNode;
}
tail->next = newNode;
newNode->next = NULL;
tail = newNode;
}
Library::book *Library::initNode(string s, int i)
{
book *ptr = new book;
if (ptr == NULL)
return static_cast<book *>(NULL);
else
{
ptr->tittle = s;
ptr->number = i;
return ptr;
}
}
void Library::displayNode(book *ptr) const
{
cout << ptr->number << ": " << ptr->tittle << endl;
}
void Library::displayList(book *ptr) const
{
if (!ptr)
cout << "Nothing to display" << endl;
while (ptr)
{
displayNode(ptr);
ptr = ptr->next;
}
}
main.cpp
#include "Library.h"
#include <iostream>
using namespace std;
int main()
{
Library a;
Library::book *ptrr;
ptrr = a.initNode("s1", 1);
a.addNode(ptrr);
ptrr = a.initNode("s2", 2);
a.addNode(ptrr);
a.displayList(a.head);
}
When you call the first a.addNode(ptrr) from main it does tail->next = newNode; (within Library::addNode), but, as tail is NULL (not assigned yet), it crashs....
Now, there could be other problems in the code, but this is most likely the first one that will make the program stop working...
Note that some stuff in your code could be simplified.
Like:
Library::book *Library::initNode(string s, int i)
{
book *ptr = new book;
if (ptr == NULL)
return static_cast<book *>(NULL);
else
{
ptr->tittle = s;
ptr->number = i;
return ptr;
}
}
could simply be:
Library::book *Library::initNode(string s, int i)
{
book *ptr = new book;
if (ptr != NULL)
{
ptr->tittle = s;
ptr->number = i;
}
return ptr;
}
And:
void Library::addNode(book *newNode)
{
if (head == NULL)
{
head = newNode;
head = newNode;
}
tail->next = newNode;
newNode->next = NULL;
tail = newNode;
}
Should be:
void Library::addNode(book *newNode)
{
if ( newNode != NULL ) // just in case
{
if (head == NULL)
{
head = newNode; // one is enough
}
if ( tail != NULL ) // to fix your crash
tail->next = newNode;
newNode->next = NULL;
tail = newNode;
}
}
Also, see user4581301 comment, the destructor code does not even compile....
I wrote this LinkedList template class, which isn't finished yet- I have yet to add safety features and more methods. As of now it does what I need it to. But it fails in a certain situation and I don't know why.
template<class data_type> class LinkedList {
private:
struct Node {
data_type data;
Node* prev;
Node* next;
Node() : prev(NULL), next(NULL) {}
};
Node* head;
Node* GetLastNode() {
Node* cur = head;
while (cur->next != NULL)
cur = cur->next;
return cur;
}
public:
LinkedList() {
head = new Node;
head->prev = head;
head->next = NULL;
}
LinkedList(LinkedList<data_type> &to_copy) {
head = new Node;
head->prev = head;
head->next = NULL;
for (int i = 1; i <= to_copy.NumberOfItems(); i++) {
this->AddToList(to_copy.GetItem(i));
}
}
~LinkedList() {
DeleteAll();
delete head;
head = NULL;
}
void AddToList(const data_type data) {
Node* last = GetLastNode();
Node* newnode = last->next = new Node;
newnode->prev = last;
newnode->data = data;
}
void Delete(const unsigned int position) {
int currentnumberofitems = NumberOfItems();
Node* cur = head->next;
int pos = 1;
while (pos < position) {
cur = cur->next;
pos++;
}
cur->prev->next = cur->next;
if (position != currentnumberofitems)
cur->next->prev = cur->prev;
delete cur;
}
void DeleteAll() {
Node* last = GetLastNode();
Node* prev = last->prev;
while (prev != head) {
delete last;
last = prev;
prev = last->prev;
}
head->next = NULL;
}
data_type GetItem(unsigned int item_number) {
Node* cur = head->next;
for (int i = 1; i < item_number; i++) {
cur = cur->next;
}
return cur->data;
}
data_type* GetItemRef(unsigned int item_number) {
Node* cur = head->next;
for (int i = 1; i < item_number; i++) {
cur = cur->next;
}
return &(cur->data);
}
int NumberOfItems() {
int count(0);
Node* cur = head;
while (cur->next != NULL) {
cur = cur->next;
count++;
}
return count;
}
};
I stated my problem in the question and here is an example:
class theclass {
public:
LinkedList<int> listinclass;
};
void main() {
LinkedList<theclass> listoftheclass;
theclass oneclass;
oneclass.listinclass.AddToList(5);
listoftheclass.AddToList(oneclass);
cout << listoftheclass.GetItem(1).listinclass.GetItem(1);
}
I can't figure out why it doesn't run right.
You need to implement an assignment operator. The problem starts in this function here:
void AddToList(const data_type data) {
Node* last = GetLastNode();
Node* newnode = last->next = new Node;
newnode->prev = last;
newnode->data = data; <---------------------------- Right there
}
Since data_type is your class, and you don't have an appropriate assignment operator, you are just getting a member by member(shallow) copy there.
See The Rule of Three
You should also probably implement a swap function, and have your assignment operator use that.
See Copy and Swap Idiom
In C++03, local classes can't be template arguments. Move theclass outside of main, and it will work.
In C++0x this limitation is removed.