Stack overflow with my destructor - c++

this is my first post to stack overflow. I'm creating a program to parse text into a linked list alphabetically, and to keep track of the count of each word. The program runs fine (by fine I mean 15 minutes which is obviously slow and not using a strong data structure) until my program returns and tries to deconstruct the dynamically allocated memory. Could someone help identify what pieces of this code I may need to adjust to avoid overflowing my stack?
template <class T>
void WordList<T>::destroyWord(WordList<T> *node)
{
WordList<T>* nodeD = NULL;
for(; node != NULL; )
{
if(node == NULL)
return;
else if(node->mNext != NULL)
{
nodeD = node;
node = node->mNext;
}
else
{
// We have found the node to delete.
//destroyWord(node->mNext);
if( node->mNext == NULL )
{
if( nodeD != NULL )
{
nodeD->mNext = NULL;
delete nodeD;
}
else
{
node = NULL;
}
}
nodeD = NULL;
}
}
// **********************************
// Delete the node at the root.
//delete node;
return;
}
Here is my revised code, thanks guys!....
template <class T>
void WordList<T>::destroyWord(WordList<T> *node)
{
node = node->mRootNode->mNext;
static WordList<T>* ptr = node;
for(; node != NULL && node->mNext != NULL; )
{
ptr = node->mNext;
delete (char*)node;
node = ptr;
}
delete (char*)ptr;
}

I would bet: your destructor most probably calls destroyWord. We can see that the destroyWord has a delete nodeD; statement. nodeD is type of WordList<T>, so this will cause a destructor call on WordList<T>, and that has a delete nodeD; as we have seen. There is our infinite recursion.

Related

C++ (Arduino) linked list, memory not freed when deleting a node inside the list

I am developing a Client for an Arduino like plattform and I am trying to use a generic LinkedList library to organise objects. The list consists of the following defined nodes:
template<class T>
struct ListNode
{
T data;
ListNode<T> *next;
};
However, I ran into memory problems while using the linked list. I found out that the memory is not freed when deleting nodes inside the list but I cannot figure out why since the element is obviously removed from the list. In addition, the memory is always freed when deleting the last node of the list. I am using the following destroy method for deleting elements in the list:
template<typename T>
void LinkedList<T>::destroy(int index){
if(index < 0 || index >= _size)
return;
if(index == 0) {
if (_size == 1) {
delete root->data;
delete root;
root=NULL;
last=NULL;
_size=0;
lastNodeGot = root;
lastIndexGot = 0;
isCached = false;
return;
} else {
ListNode<T> *tmp = root->next;
delete root->data;
delete root;
root = tmp;
_size--;
lastNodeGot = root;
lastIndexGot = 0;
isCached = false;
return;
}
}
ListNode<T> *tmp = getNode(index - 1);
ListNode<T> *toDelete = getNode(index);
tmp->next = toDelete->next;
delete toDelete->data;
delete toDelete;
if (tmp->next == NULL) {
last=tmp;
}
_size--;
lastNodeGot = tmp;
lastIndexGot = index-1;
isCached = false;
return;
}
If I delete all elements with the method above so that the list is empty, the memory is fully freed. However, the list is used in the client quite frequently with add/delete operations but it gets never emptied completely.
Btw. I am storing pointers to objects in the list like Strings.
Is there anything wrong with the code? Thank you in advance.

Remove a Node from a binary tree

Please help. What is wrong with my remove function below. Cant seem to figure it out
I seem to be getting an error:
The class declaration seems pretty fine. The main issue is to have this remove function to work
void binaryTree::Remove(int) {
if (node != NULL)
{
Node* tmptr = node;
int rootdata = node->data;
/int rSubtree;
}
{
// Case 0- no child
if (node->lChild == NULL && node->rChild == NULL)
{
node = NULL;
//parent- //set the parent of the node to NULL
delete node;
}
// has one child
else if (node->lChild == NULL && node->rChild != NULL)
{
node = node->rChild;
node->rChild = NULL;
delete node;
}
else if (node->lChild != NULL && node->rChild == NULL)
{
node = node->lChild;`enter code here`
node->lChild = NULL;
delete node;
}
}
Try swapping node = NULL with delete node; Otherwise you're trying to delete NULL.

How to delete a linked list without recursion?

I'm trying to find a way of deleting a linked list without recursion, because a stack overflow isn't really something nice.
I have a struct as follows:
typedef struct _my_Item
{
_my_Item(const std::string& name)
{
m_name = name;
}
~my_Item()
{
delete next; // this recursively deletes the "tail" of the list
next = NULL;
}
struct _my_Item *next;
std::string m_name;
// ... More members here...
}
In some piece of code (not relevant here) I'm constructing a list from a data file using the above structure. I keep the pointer to the head of the list in a variable and can work with it. All fine.
When I finally call the destructor on the head of the list, the destructor gets called and the delete next; causes a recursion to delete the "tail" of the list (which is the entire list without the first element). Now since the list is quite long, I see a stack overflow sometimes.
Is there a nice way to get around this problem?
~my_Item()
{
while (next)
{
_my_Item* item = next;
next = item->next;
item->next = NULL; // this prevents the recursion
delete item;
}
}
Create a class representing the list itself that will encapsulate nodes deletion in its destructor via a for/while loop. Doing it the way you do leaves the possibility to delete part of the list and leave dangling pointer.
One suggestion would be to remove the delete code from the destructor and use a pointer to delete the list.
struct _my_Item * nodeToDelete = NULL;
while(firstNode != NULL)
{
nodeToDelete = firstNode;
firstNode = firstNode->next;
delete nodeToDelete;
}
// I wrote this java code to delete a node from BST
// I only used one recursion call to remove successor
public Boolean delete(int data){
if(isEmpty() || !search(data))
return false;
return delete(null,root,data);
}
public Boolean delete(Node parent,Node temp,int data) {
while(true){
if(data == temp.getData()) {
break;
} else if(data < temp.getData()) {
parent = temp;
temp = temp.getLeft();
} else {
parent = temp;
temp = temp.getRight();
}
}
if(parent == null && (temp.getLeft() == null || temp.getRight() == null)){
if(temp.getLeft() == null)
root = temp.getRight();
else
root = temp.getLeft();
} else if(temp.getLeft() == null || temp.getRight() == null) {
if (parent.getLeft() == temp) {
if (temp.getLeft() == null)
parent.setLeft(temp.getRight());
else
parent.setLeft(temp.getLeft());
} else if (parent.getRight() == temp) {
if (temp.getLeft() == null)
parent.setRight(temp.getRight());
else
parent.setRight(temp.getLeft());
}
}else{
int min = findMin(temp.getRight());
temp.setData(min);
delete(temp,temp.getRight(),min);
}
return true;
}

unsorted linked list implementation check full

I am working on unsorted linked list check full currently, below is my specification and implementation.
Specification:
#ifndef UNSORTEDLIST_H
#define UNSORTEDLIST_H
#include <iostream>
using namespace std;
struct Node {
float element;
Node* next;
};
class UnsortedList
{
public:
UnsortedList();
bool IsEmpty();
bool IsFull();
void ResetList();
void MakeEmpty();
int LengthIs();
bool IsInTheList(float item);
void InsertItem(float item);
void DeleteItem(float item);
float GetNextItem();
private:
Node* data;
Node* currentPos;
int length;
};
#endif
And implemetation:
UnsortedList::UnsortedList()
{
length = 0;
data = NULL;
currentPos = NULL;
}
bool UnsortedList:: IsEmpty(){
if(length == 0)
{
return true;
}
else
{
return false;
}
}
bool UnsortedList::IsFull(){
Node* ptr = new Node();
if(ptr == NULL)
return true;
else
{
delete ptr;
return false;
}
}
void UnsortedList::ResetList(){
currentPos = NULL;
}
void UnsortedList::MakeEmpty()
{
Node* tempPtr = new Node();
while(data != NULL)
{
tempPtr = data;
data = data->next;
delete tempPtr;
}
length = 0;
}
int UnsortedList::LengthIs(){
return length;
}
bool UnsortedList:: IsInTheList(float item){
Node* location = new Node();
location = data;
bool found = false;
while(location != NULL && !found)
{
if(item == location->element)
found = true;
else
location = location->next;
}
return found;
}
void UnsortedList:: InsertItem(float item){
Node* location = new Node();
location->element = item;
location->next=data;
data = location;
length++;
}
void UnsortedList:: DeleteItem(float item){
Node* location = data;
Node* tempPtr;
if(item == data->element){
tempPtr = location;
data = data->next;
}
else{
while(!(item == (location->next) ->element) )
location = location->next;
tempPtr = location->next;
location->next = (location->next)->next;
}
delete tempPtr;
length--;
}
float UnsortedList::GetNextItem(){
if(currentPos == NULL)
currentPos = data;
else
currentPos = currentPos->next;
return currentPos->element;
}
1.In the constructor, why don't assign currentPos as null?
2.In the IsInTheList function, Why points to pointer "next" ? Isn't next is a null pointer since it has been declared in struct as Node* next?
The pointer value is not set to NULL value by default, you should set to to null explicitly. Also instead of using NULL, choose using nullptr.
This code is rather incomplete, so it is difficult to answer your questions.
This does not contain the code to insert an item in the list, which is where I would expect both the next and currentPos pointers to be set. However, that's based on a number of assumptions.
However, I don't see where next is used in the "check full function" at all, so that question is a bit confusing.
I'll also point out that this code has a glaring memory leak. The first line in IsInTheList allocates memory for a new Node, which is immediately lost with location = data.
Pointers (like any other basic type) need to be initialized before use. A value of NULL is still a value.
The code you provided seems to be very incomplete. Is data supposed to be the head of your list? I am not sure how you define "fullness". If you want to test if the list is empty, you can see if your "head" of the list is null:
bool UnsortedList::IsEmpty() {
if (data == NULL) {return true;} // if there is no first element, empty
else {return false;} // if there is ANY element, not empty
}
Or more compactly:
bool UnsortedList::Empty() {
return (data == NULL);
}
When a node is added to a linked list, we usually add the node as a whole and modify the element that came before it. For example, we might create a new node and add it using code like the following:
// implementation file
void UnsortedList::InsertItem(const float& item) {
if (data == NULL) { // no elements in list, so new node becomes the head
data = new Node; // allocate memory for new node
data->element = item; // fill with requested data
data->next = NULL; // there is no element after the tail
}
else {
new_node = new Node; // allocate memory
new_node->element = item // set data
new_node->next = NULL; // new end of the list, so it points to nothing
tail->next = new_node; // have the OLD end node point to the NEW end
tail = new_node; // have the tail member variable move up
}
}
// driver file
int main() {
UnsortedList my_list;
float pie = 3.14159;
my_list.AddNode(pie);
return 0;
}
Please note that I made use of a Node* member variable called tail. It is a good idea to keep track of both where the list begins and ends.
In your IsFull function, it will always return false since it can always create a new Node*. Except perhaps if you run out of memory, which is probably more problematic.
Your functions are rather confusing and your pointer work leaves many memory leaks. You might want to review the STL list object design here.

adding node at last in Linked List in C++

I have tried to implement Singly Linked List. My addAtLast() function is not getting executed properly. Program crashes while executing this function. Kindly suggest some changes.
class LList
{
public:
int noOfNodes;
Node const *start;/*Header Node*/
LList()
{
start=new Node;
noOfNodes=0;start=0;
}
void addAtFront(Node* n)
{
/*
cout<<endl<<"class"<<n;
cout<<"start"<<start;
cout<<"data in node";n->print();
*/
n->next=const_cast<Node*>(start);
start=n;
// cout<<" next=";start->print();
noOfNodes++;
}
void addAtLast(Node* n)
{
Node *cur=const_cast<Node*>(start);
if (start==NULL)
{
start=n;
return;
}
while(cur->next!=NULL)
{
cur=cur->next;
}
cur->next=n;
noOfNodes++;
}
int getPosition(Node data)
{
int pos=0;
Node *cur=const_cast<Node*>(start);
while(cur!=NULL)
{
pos++;
if(*cur==data)
{
return pos;
}
cur=cur->next;
}
return -1;//not found
}
Node getNode(int pos)
{
if(pos<1)
return -1;// not a valid position
else if(pos>noOfNodes)
return -1; // not a valid position
Node *cur=const_cast<Node*>(start);
int curPos=0;
while(cur!=NULL)
{
if(++curPos==pos)
return *cur;
cur=cur->next;
}
}
void traverse()
{
Node *cur=const_cast<Node*>(start);
while(cur!=NULL)
{
// cout<<"start"<<start;
cur->print();
cur=cur->next;
}
}
~LList()
{
delete start;
}
};
void addAtLast(Node* n) {
Node *cur=const_cast<Node*>(start);
if(start==NULL) {
start=n;
n->next = NULL;
noOfNodes++;
return;
}
while(cur->next!=NULL) {
cur=cur->next;
}
cur->next=n;
n->next = NULL; // Added
noOfNodes++;
}
I mentioned this in-comment, but will address it here as an answer. The caller of this function must ensure two things:
That the passed-in node list (and it is a list, even if only one element long) must be properly terminated with an end-next-pointer set to NULL. The caller must ensure this, as this code cannot assume it and blindly set node->next = NULL;
Make absolutely sure the caller is aware that once this executes, this list now owns the passed-in node and any list it potentially starts and the caller, therefore, must NOT free it, or anything it points to, on the caller side.
Apart from the node-count management issue, there is nothing wrong with the addAtLast() function, though I would have implemented it a little differently:
void addAtLast(Node* n)
{
// no nulls allowed
if (n == NULL)
return;
// set start if first in list
if (start == NULL)
{
start = n;
noOfNodes = 1;
}
// else walk list to find end
else
{
Node *cur = const_cast<Node*>(start);
while(cur->next != NULL)
cur = cur->next;
cur->next = n;
++noOfNodes;
}
// adjust count to contain any nodes from 'n'
while (n->next != NULL)
{
++noOfnodes;
n = n->next;
}
}
From the beginning..
start=new Node;
noOfNodes=0;start=0;
Should this be?
start=new Node;
noOfNodes=0;start->next=NULL;
Within 2 lines you've created memory leak. I have no idea why you would want to set start=0. Don't do that, you've just assigned memory to it!
As for the crash, it's addressed by #liulinhuai's answer. You'll be dereferencing a pointer that is uninitialized attempting to get it's next member.
In your ctor you set start as 0. In your crash function you first check it for NULL:
if (start==NULL)
{
start=n;
//n->next is now points to nowhere
return;
}
Next call to addAtLast iterate until it finds NULL but previous assign didnt set next pointer to NULL so second iteration will cause an access violation:
while(cur->next!=NULL) {
//first time it's ok but second call on cur will crash
cur=cur->next;
}
Solution is - all new Node's must have next pointer setted to NULL