Im losing elements in my dynamically allocated arrays - c++

Im implementing a stack which allocates a new array when the current array is full. It uses a linked list to keep the addresses of these arrays. When the stack pop()s the only element in an array, it deletes the array, deletes the linked list node which contains this array's address, then reverts to the next node (which is now in the front) and uses the array address within the node as its new "current array"
This is not working and I cannot change the basic structural requirement. The array deletes successfully, the node deletes successfully but for some reason, the old array seems to contain no data anymore and the function generally just breaks. Is there anything you can spot in these function definitions which obviously is the problem?:
Here the members (minus function prototypes and full LL def):
class Stack
{
private:
int height;
class LL
{
...
}
LL stack_map;
string * current_stack;
public:
int top_element;
Constructor:
Stack::Stack(int size)
{
height = size;
top_element = 0;
current_stack = new string[height];
stack_map.push_front(current_stack);
}
Push function:
void Stack::push(string data)
{
if (top_element == height)
{
current_stack = new string[height];
stack_map.push_front(current_stack);
current_stack[0] = data;
top_element = 1;
}
else
{
current_stack[top_element] = data;
top_element++;
}
}
And pop functions
bool Stack::pop(string& result_box)
{
if (top_element == 0)
{
delete[] current_stack;
cout << "Array deleted" << endl;
stack_map.delete_front(current_stack);
cout << "number of nodes :" << stack_map.list_length() << endl;
top_element = height - 1;
cout << current_stack[top_element];
result_box = current_stack[top_element];
return true;
}
else
{
top_element--;
result_box = current_stack[top_element];
return true;
}
}
Lastly here is the push_front and delete_front functions called in these:
push:
void push_front(string * current_stack)
{
LLnode * new_node;
new_node = new LLnode;
new_node -> stack_address = current_stack;
if (header == nullptr)
{
header = new_node;
new_node -> fwdPtr = nullptr;
}
else
{
LLnode * temp;
temp = header;
header = new_node;
new_node -> fwdPtr = temp;
}
return;
}
delete:
void delete_front(string * current_stack)
{
LLnode * temp, * kill_box;
if (header == nullptr)
{
return;
}
else
{
kill_box = header;
temp = header -> fwdPtr;
delete kill_box;
header = temp;
current_stack = temp -> stack_address;
}
}
I know this is a horrendous amount of code, I just dont understand the problem enough to minimize it further. Im not receiving errors, but my testing is not able to retrieve any strings once the pop() function tries to move back to a previous node/array.
Any advice is appreciated.

Ultimately I found the bug. The function delete_front(), which is responsible for changing the string * current_stack pointer was passed by value and not by reference. Therefore, it was never pointing at anything but the already-deleted array.
This is why it appeared like I was "losing data", my pointer was always pointing at the deleted array instead of changing as node/arrays were deleted. I was so pleased when I found this. Maybe this can help someone in the future, it definitely will be a good reference for me.

Related

Avoid memory leak when removing last node from deque using linkd list

For my homework, I need to make methods that add (append) and remove (serve) nodes from a Deque. However, when trying to serve the last node I struggle with memory leaks since I don't know how to retrieve the node that's not being used anymore to the system.
Here's the code for the method.
void Deque::serveAtRear(int &x)
{
if(empty())
{
cout << "Fila Vazia" << endl;
exit(0);
}
else
{
DequePointer q; //Pointer before p
q = head; //q starts at the deque's head
p = head->nextNode; //Pointer for the next node
if(q->nextNode==NULL) //If there's only one node
{
x = q->entry; //x will receive the value of the removed node to print it afterward
head = tail = NULL;
delete p; //I don't know if I'm using the "delete" right
}
else
{
while(p->nextNode != NULL)
{
p = p->nextNode;
q = q->nextNode;
if(p->nextNode==NULL)
{
q->nextNode=NULL;
}
}
x = p->entry;
delete p->nextNode;
}
delete q->nextNode;
}
}
To add nodes I have this method:
void Deque::appendAtFront(int x)
{
if(full())
{
cout << "FULL" << endl;
exit(0);
}
else
{
p = new DequeNode;
p->entry=x;
if(p == NULL)
{
cout << "Can't insert" << endl;
exit(0);
}
else if(empty())
{
head = tail = p;
p->nextNode=NULL;
}
else
{
p->nextNode=head;
head = p;
}
}
}
Also I can't use the "deque" lybrary
Generic answer to how avoid leaks is: avoid manual memory allocation.
For example you can use smart pointers, e.g. std::unique_ptr and instead of calling new DequeNode call std::make_unique<DequeNode>(). Compiler will then point places where your code needs to be adapted, as you will limit yourself so that each of your DequeNode(s) will be owned by just one unique_ptr at the same time. Example pop function (where head and DequeNode.next are uniuque_ptrs) based on your serveAtRear:
if (!head)
{
return;
}
DequeNode* q; //Pointer before p
DequeNode* p; //will be tail eventually
q = head.get(); //q starts at the deque's head
p = q->next.get(); //Pointer for the next node
if(!p) //If there's only one node
{
x = q->entry; //x will receive the value of the removed node to print it afterward
head.reset(); // hear we release DequeNode pointed by head
}
else
{
while(p->next)
{
q = p;
p = q->next.get();
}
x = p->entry;
q->next.reset(); // here we release tail (i.e. p)
}
Of course implementation of push needs to be adopted too :).

a loop that prints all the items (no matter how long the chain is) *pointers

The following is a basic code and I was wondering what was the basic way to write a loop on how to display the contents/data from the array of pointers. The top is a class with everything under public. Declaring a data of string followed by an array of pointers called next. In the main function, I'm declaring a few nodes and allocating memory to its followed by a string. A, B, and C. Towards the end of the code I'm connecting the pointers to each data and the last one C to NULL. And at the end, I'm having a bit of trouble writing or grasping the concept on how to write a loop to display it's contents, i.e Node1, Node2, Node3... Preferably a loop that'll display everything no matter the size.
#include <iostream>
using namespace std;
class node
{
public:
string data;
node * next;
};
int main()
{
node * A;
A = new node;
(*A).data = "node1";
node * B;
B = new node;
(*B).data = "node2";
node * C;
C = new node;
(*C).data = "node3";
(*A).next = B;
(*B).next = C;
(*C).next = NULL;
for(int i=0; *(next) != NULL; i++)
{
cout << *next[i[] << endl;
}
system("pause");
return 0;
}
use a temporary pointer that's initialized with the start of the node and use a while loop.
Node* tmp = A;
while (tmp) { // same as (tmp != NULL)
cout << tmp->data << endl;
tmp = tmp->next; // down the rabbit hole
}
Also, You could collapse the declaration of variables with assignment.
Node* A = new Node;
1.) remove for loop
printList(A);
void printList(node *first)
{
node *first = A;
while(first)
{
cout<<first->data<<endl;
}
}

C++ Add node to beginning of linked list fails after 1 time. Trouble with other methods too

So I have a linked list program semi working. I am just having some trouble with certain methods.... The ones I have documented bekiw are working except for delete from end which is acting weird.
I am using NetBeans on Mavericks with G++ as my compiler and C++11
Here is a zip of all of the program files
Here is a list of the methods I am trying to make:
//working
int size() const;
/kind of
void addToStart(Node *);
//working
void addToEnd(Node *);
//working
void printList();
//working
bool removeFromStart();
//kind of working
bool removeFromEnd();
//Still working on these
void removeNodeFromList(int);
void removeNodeFromList(string);
For now, I have to run removeFromEnd() twice in order for it to work. Meaning, I run it once at the beginning of the program and it does nothing, but every subsequent time, it actually does the deleting.
For addToStart() it works if I only run it once. I.E:
I can run it once at the beginning of the program and print out the list
I can run it once AFTER using addToEnd, but if I try it a second time, and I try to print out the list, it just keeps spitting out the value I tried to add.
addToEnd() works perfectly find if I just keep running that, but it fails if I:
Start out by using addToEnd() to add items, then use addToStart() ONCE and THEN try to use addToEnd() again. When I print out the list, it only prints out two objects and each of those is a copy of the last value I tried to insert.
void LinkedList::addToEnd(Node* ne)
{
Node** q = &myHead;
while (*q)
{
q = &(*q)->next;
}
*q = new Node(ne->itemName, ne->itemNo);
}
void LinkedList::printList()
{
Node* p = myHead;
while (p != NULL)
{
cout << p->itemNo << " " << p->itemName;
cout << endl;
p = p->next;
}
cout << endl << endl;
}
bool LinkedList::removeFromStart()
{
if (myHead == NULL)
{
cout << "List is already empty";
}
else
{
myHead = myHead->next;
}
}
bool LinkedList::removeFromEnd()
{
if (myHead == NULL)
return false;
//Empty the list if there's only one element
if (myHead->next == NULL)
{
delete myHead;
myHead = NULL;
myTail = NULL;
return true;
}
// Find the last item in the list
Node *temp = myHead;
while (temp->next != myTail)
{
temp = temp->next;
}
delete myTail;
temp->next = NULL;
myTail = temp;
return true;
}
Also, still trying to figure out the remove ones
void LinkedList::removeNodeFromList(int i) {
//Save the values
Node* p = myHead;
Node* temp = myHead->next;
while (p) {
if (p->itemNo == i) {
p=temp;
} else {
p = p->next;
}
}
}
You have a tail pointer, so why are you iterating through the list to find the end? Additionally, why are you passing the node by pointer?
void LinkedList::addToEnd(Node ne)
{
if (myHead == nullptr) // empty list
{
myHead = myTail = new Node(ne);
myTail->next = nullptr;
}
else
{
myTail->next = new Node(ne); // assuming Node has an accessible copy constructor
myTail = myTail->next;
}
}
The removeFromStart function has a memory leak:
bool LinkedList::removeFromStart()
{
if (myHead == nullptr)
{
cout << "List is already empty";
return false;
}
Node* temp = myHead;
myHead = myHead->next;
if (myTail == temp) // if there is only 1 element in the list, head == tail
{
myTail = myhead;
}
delete temp;
return true;
}
Presumably, removeFromEnd should be removing the tail:
bool LinkedList::removeFromEnd()
{
if (myTail == nullptr)
return false;
// unless you have a doubly-linked list, loop to find 1 before the tail
Node* temp = nullptr;
for (temp = myHead; temp && temp->next != myTail; temp = temp->next);
if (myHead == temp) // when there is only 1 element in the list, head == tail
{
delete temp->next;
myHead = nullptr;
myTail = nullptr;
}
else
{
delete temp->next;
temp->next = nullptr;
myTail = temp;
}
return true;
}
And yes, you are using new (in your addtoEnd function), so you must use delete (not free!).
Side note: You can write the remove code better by using std::unique_ptr (you can actually improve the code overall by using it everywhere) which will make your code for each about 4 lines long. I'll leave that for you to implement.
You have a member called myTail that you seem to be using 'sometimes'
In addFromEnd you do not update myTail.
In one of the remove functions you do not update myTail even though you might change it
But in RemoveFromTail you are trying to use it.
There is no reason that myTail will contain a valid value and when you try to use it you can get an error (cause the node may have been deleted) or an unexpected result because it just points somewhere in the list.
You should either lose it (since you can easily figure out the tail. it is the node where next==NULL) or take care to maintain it in every call that changes the List (only if the tail is affected obviously)
Since you are using c++11 a few suggestions:
use nullptr instead of NULL
use std::unique_ptr for Next. It will take care of 'deleting' nodes you are no longer using for you.
use a copy ctor for Node. If you ever make a change to Node you will not need to revisit this part of the code just the constructors.
If you are holding copies of objects in the list. Then it is much clearer if your interface will accept const Node& instead of Node*. To me Node* makes it seem like you are going to use the ptr the user supplied.

C++ Executable Freezes at Runtime

I wrote a simple console program for the use of testing some key classes in a library I'm building. Now, the code builds correctly with no errors. But, after executing the code, I found that the application stops working after calling the Index method at a certain point in the code. I tried debugging a few different ways to get more information about the problem, but the information I gathered didn't help me at all. Maybe it will help someone else who knows what I'm not doing(or doing incorrectly).
Here's the contents of the Util namespace;
template<typename var>
class VectorNode
{
public:
VectorNode(var value, VectorNode<var>* next = NULL, VectorNode<var>* prev = NULL)
{
data = value;
t_next = next;
t_prev = prev;
}
~VectorNode()
{
if (t_next != NULL)
delete t_next;
}
virtual VectorNode<var>* Next(){ return t_next; } // get the next node in line
virtual void Next(VectorNode<var>* newNode){ t_next = newNode; } // set the next node in line
virtual VectorNode<var>* Prev(){ return t_prev; }// get the previous node in line
virtual void Prev(VectorNode<var>* newNode){ t_prev = newNode; } // set the previous node in line
virtual var Value(){ return data; } // get the node's value
private:
var data;
VectorNode<var>* t_next;
VectorNode<var>* t_prev;
};
template<typename var>
class Vector
{
public:
Vector()
{
tailNode = new VectorNode<var>(*(new var));
headNode = new VectorNode<var>(*(new var), tailNode);
tailNode->Prev(headNode);
size = new int;
*size = 0;
}
~Vector()
{
delete headNode;
delete size;
}
int Size(){ return *size; } // get the size of a vector
void Add(var toAdd, int index = 0) //
{
VectorNode<var>* lastNode;
if (index > (*size))
index = *size;
if (index < 1) // add to the end of the vector
{
lastNode = tailNode;
}
else
{
int i;
if (index <= (*size / 2)) // if the index is less than half the size, iterate forwards
{
lastNode = headNode;
for (i = 1; i <= index; i++){ lastNode = lastNode->Next(); }
}
else // otherwise, iterate backwards
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev(); }
}
}
VectorNode<var>* temp = lastNode->Prev();
VectorNode<var>* newNode = new VectorNode<var>(toAdd, lastNode, temp);
lastNode->Prev(newNode);
temp->Next(newNode);
*size = *size + 1;
}
void Remove(int index) // remove an index
{
VectorNode<var>* toRemove;
VectorNode<var>* lastNode;
int i;
if ((index > *size) || (index < 1)) // if not in the domain...
index = *size;
if (index <= (*size / 2)) // iterate forwards
{
lastNode = headNode;
for (i = 1; i < index+2; i++){ lastNode = lastNode->Next(); }
}
else // iterate backwards
{
lastNode = tailNode;
for (i = *size; i > index; i--){ lastNode = lastNode->Prev(); }
}
toRemove = lastNode->Prev();
VectorNode<var>* temp = toRemove->Prev();
temp->Next(lastNode);
lastNode->Prev(temp);
delete toRemove;
*size = *size - 1;
}
var Index(int index) // get the value of a node
{
VectorNode<var>* lastNode;
int i;
if (index <= (*size / 2)) // iterate forwards
{
lastNode = headNode;
for (i = 1; i <= index; i++){ lastNode = lastNode->Next(); }
}
else // iterate backwards
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev();}
}
return lastNode->Value();
}
private:
int* size;
VectorNode<var>* tailNode; // the head and tail nodes are placeholders, to keep the list inside its boundaries
VectorNode<var>* headNode;
};
If you don't feel like reading that, I marked each method with a comment, explaining its overall purpose. Also, I tried adding a small explanation of some of my blocks of code.
And, here's the entry function, and inclusions;
#include "iostream"
#include "stdlib.h" // this has nothing in it that's being used
#include "testhead.h" // the location of the Util namespace
int main()
{
using namespace Util;
Vector<int>* x = new Vector<int>();
x->Add(42);
x->Add(24);
x->Add(12);
x->Add(21);
std::cout << "Listing Indices\n";
for (int i = 1; i <= x->Size(); i++)
{
std::cout << i << "\t" << x->Index(i) << "\n";
}
std::cout << "Size(pre-removal):\t" << x->Size() << "\n";
x->Remove(2);
std::cout << "Size(post-removal):\t" << x->Size() << "\n";
std::cout << "Listing Indices\n";
std::cout << 3 << "\t" << x->Index(3) << "\n";
for (int i = 1; i <= x->Size(); i++)
{
std::cout << i << "\t" << x->Index(i) << "\n";
}
system("Pause");
}
Okay, the results I got where this. Before using the Remove method, any index can be accessed from the Vector class freely. But, after using the remove method, no matter what index is removed, no index above one can be accessed. Except, in the case which we remove the first index, then no indices can be accessed. I tried stepping through the code, but it brought me up to this line of code in the index method;
else
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev();} // error occurs after running this line
}
Now, since I was able to figure out the Remove method was causing the problem, I went back and got some output about that. I had it run the following line prior to finishing its execution, twice. Once before toRemove is deleted, and once again after it is deleted.
std::cout << (lastNode->Prev() == temp) << "\t" << (temp->Next() == lastNode) << "\n";
Before it is removed, it prints 1 twice, indicating the comparison was true. But, the second time I call either the Prev and Next method, and the program freezes. I know this is because I freed the place in memory, but the comparison shows that any references from other nodes to the node I removed were gone. Now, my specific question is why exactly this is being caused, and how can I fix it? I know a little bit about managing memory on the heap, and this doesn't exactly appear as though it would cause any issues with the program. So, I could use a short explanation as to why this happens if anyone would be kind enough to provide it.
If it's any assistance, I'm using the Code::Blocks IDE and the GNU GCC compiler. Also, please tell me if I'm doing something wrong related to the way I asked my quetsion. I don't visit Stack Overflow often, and I don't ask questions here. This is just the best place to have your questions answered that I am aware of.
The destructor of the VectorNode class deletes the object pointer to by the t_next pointer. Calling delete on the toRemove pointer means that the destructor of that VectorNode object gets called, and then the next one, and then the next one etc. etc.
So basically, when you delete toRemove, you delete toRemove and all the objects that come after this. This causes the tailNode's t_prev to point to memory that you have already freed, and you then try dereferencing those pointers in your Index function, and that's not a good thing.
When you delete a VectorNode that has its t_next member pointing to some other node, the destructor of VectorNode will delete that other node (which in turn might go on to delete further nodes).
When you remove a node from the middle of a list with Remove(), the t_next of this node will point to the further nodes of the list. When this node is deleted, the destructor will also delete all the nodes following it in the list. Continuing to use this half-deleted list it will result in all kinds of problems.
Other random observations:
Why is size a int* instead of a normal int or size_t? I can't see any reason why this should be a pointer.
new VectorNode<var>(*(new var)) should really be new VectorNode<var>(var()) to not unnecessarily leak memory.
The t_next != NULL test before delete is unnecessary
Are you planning to create classes deriving from VectorNode<>? If not, than there is no reason why the methods would need to be virtual.
Using 1-based indexing in Add() is unusual, one would expect zero-based indexing
Also I feel obliged to tell you that there are standard library containers like std::list<> and std::vector<> which implement this kind of structures.
Calling remove deletes a node, but deleting a node deletes all the nodes->next
~VectorNode()
{
if (t_next != NULL)
delete t_next;
}
so deleting element 2 of your 1 based vector kills all the other elements as you have experienced, and there is no longer an element 3 to investigate

Why can't the Nodes be linked together?

EDIT: Is it possible to NOT use new? (do not dynamically allocating memory)
I think it is push that is wrong, but I don't know where, how, and why. here is the code:
struct Node {
string fileName;
Node *link;
};
int size(Node *&flist) {
int count = 0;
Node *tempPtr = flist;
while (tempPtr != 0) {
count += 1;
tempPtr->link = (tempPtr->link)->link;
}
return count;
}
Node* push(Node *&flist, string name) {
Node temp;
Node *tempPtr = &temp;
temp.fileName = name;
temp.link = flist;
cout << tempPtr->fileName << endl;
cout << (tempPtr->link)->fileName << endl;
return tempPtr;
}
int main( int argc, char *argv[] ) {
Node aNode;
Node *flist = &aNode;
flist->fileName = "a";
flist->link = NULL;
push(flist, "b");
int s = size(flist);
cout << "size: " << s << endl;
}
the output is
b
a
size: 0
Thank you.
In your size() function you are modifying the list in the loop. You don't want to modify tempPtr->link but rather just change tempPtr as you iterate. Changing tempPtr won't modify anything permanently. You should also avoid passing flist by reference here as there's no need to modify it. So:
int size(Node *flist) {
int count = 0;
Node *tempPtr = flist;
while (tempPtr != 0) {
count += 1;
tempPtr = tempPtr->link;
}
return count;
}
As for push(), the biggest problem is that you're allocating the new node as a local variable which means it'll be on the stack and will get destroyed when the function returns. To create a node that is more permanent you need to allocate it on the heap using the new operator. And again the '&' for flist is unnecessary:
Node* push(Node *flist, string name) {
Node *tempPtr = new Node;
tempPtr->fileName = name;
tempPtr->link = flist;
cout << tempPtr->fileName << endl;
cout << tempPtr->link->fileName << endl;
return tempPtr;
}
Note that the counterpart to new is delete. Since the new nodes are allocated on the heap they will not be destroyed automatically so you will need to manually delete them when you are done with the list. Your goal is to have one delete for every new, so if you new 5 nodes your code should delete 5 nodes when it cleans up. If you don't do this your program will run fine but it will have a small memory leak.
(Actually, when it exits all allocated memory is automatically freed. But it's a bad habit to allocate memory and never free it, in general, so you should pretend this automatic cleanup doesn't happen.)
Well, your size() function is a little overkill. You might try
int size(Node *flist) {
int count = 0;
Node *tempPtr = flist;
while (tempPtr) {
count += 1;
tempPtr=tempPtr->link;
}
return count;
}
I've removed an extraneous exit condition from the while statement that prevented calculation of the length of lists that have only one element.
The reason it's returning 0 in your version is that your while statement:
while ((tempPtr != 0) &&(tempPtr ->link != 0)) {
count += 1;
tempPtr->link = (tempPtr->link)->link;
}
never executes since your one node has a .link value of null (0). Try the modified version I provided above.
Oh, in the future, you might want to tag these sorts of posts as "homework." You'll get better responses.
You need to use new. Otherwise the variable temp is destroyed at the end of the push function. Later, if you try to access what that pointer pointed to, it will be GONE.