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.
Related
This question already has answers here:
Why does the object created without using "new" operator gets the same address
(2 answers)
Closed 2 years ago.
why is the address of temp (in the while loop in main) the same everytime the loop runs
i am trying to insert into a linked list and then display and then output the middle element but initially in displaying it ran an infinite loop only displayint the first element. On printing the address after inserting and llist.add_ele_to_beg(&temp); its priting the same address each time ! why is this happening ?
#include<iostream>
#include <unistd.h>
using namespace std;
class LinkedList;
class Node
{
private:
Node* next;
int value;
friend class LinkedList;
public:
Node(int ele) // constructor - declared in private section
// to prevent other classes creating objects of this class,
// only this class can create the object
{
next = nullptr;
value = ele;
}
};
class LinkedList
{
private:
Node* head;
public:
LinkedList()
{
head = nullptr;
}
void add_ele_to_beg(Node *temp)
{
// Node *temp = new Node(); // dynamically alloctg Node object
// temp->value = x;
temp->next = this->head;
this->head = temp;
}
void display()
{
Node *h = this->head;
while(h)
{
cout << h << endl;
cout << h->value << endl;
h = h->next;
cout << h << endl;
cout << h->value << endl;
exit(0);
}
}
int findMiddle()
{
Node *fast, *slow = this->head;
if(!slow)
{
return -1;
}
if(!slow->next)
{
return slow->value;
}
if(!slow->next->next)
{
return slow->value;
}
// n > 2
fast = head->next->next;
while(1)
{
slow = slow->next;
if(!fast->next)
{
if(!fast->next->next)
{
fast = fast->next->next;
}
else
{
break;
}
}
else
{
break;
}
}
return slow->value;
}
};
int main()
{
LinkedList llist;
int n;
cout << "enter n" << endl;
cin >> n;
// create a dummy node
cout << "enter elements to be inserted in the beg" << endl;
int ele;
while(n--)
{
cin >> ele;
Node temp(ele); // obj node created and ctor initialises
llist.add_ele_to_beg(&temp); // sending address of node to make change to
cout << &temp << endl;
// node (passing by reference)
}
llist.display();
cout << llist.findMiddle();
cout << endl;
return 0;
}
why is the address of temp (in the while loop in main) the same everytime the loop runs
Because object you get address of has automatic storage duration. It means that object lifetime ends at the end of block it was created (end of loop in your case) and you have dangling pointer after that. As that memory considered free after lifetime of object ends compiler reuses the same memory again for practical purpose (it does not have to, but it can and it makes sense).
To make it work properly you should create object with dynamic storage duration, which means you control lifetime of the object. You can use operator new for that, but it is better to use smart pointer instead of raw one and let it manage object lifetime. In such case you should use std::make_unique or std::make_shared depends on what kind of ownership you want. You can find details on how to do it here C++ Linked list using smart pointers
On printing the address after inserting and llist.add_ele_to_beg(&temp); its priting the same address each time ! why is this happening ?
It happens because temp is a local variable, so it lives on the stack, and the same set of local variables gets created and destroyed in the same place each time through the loop:
while(n--)
{
cin >> ele;
Node temp(ele); // obj node created and ctor initialises
llist.add_ele_to_beg(&temp); // sending address of node to make change to
cout << &temp << endl;
// node (passing by reference)
}
So temp gets created on top of the stack, and then you do some things to it, and then it goes out of scope (so gets destroyed), and then the stack is in the same state that it was in before that iteration of the loop. And then the process repeats.
It looks like what you probably mean to be doing is allocating a new node using new, so that the object is created on the heap. You can then call list.add_ele_to_beg() to add it to the list, and the object will live beyond the end of the loop's body.
You can create a new element using new Node() in each loop cycle.
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.
I didn't quite know how to describe the question -and whether there is any name for my error.
When i run the programme type some number e.g. 5 the tree.root->pocz is first 1 and later the weird number. Anyone know what's going on and how to repair it?
struct Node
{
int pocz;
int kon;
Node *left, *right, *up;
};
class AVL{
public:
Node *root;
void initiate(){
root = NULL;
}
bool insertNode(int poczPrz, int konPrz);
};
AVL tree;
//part of AVL insert function
bool AVL::insertNode(int poczPrz, int konPrz){
Node w;
w.pocz = poczPrz;
w.kon = konPrz;
Node *n = &w;
Node *x = tree.root;
Node *y, *z;
y = n->left = n->right = NULL;
while(x){
if(x->pocz == n->pocz){
delete n;
return false;
}
y = x;
x = (n->pocz < x->pocz) ? x->left : x->right;
}
if(!(n->up = y)){
cout << "We leave the function here\n";
tree.root = n;
return true;
}
if(n->pocz < y->pocz) y->left = n;
else y->right = n;
}
int main()
{
int n; cin >> n;
tree.initiate();
tree.insertNode(1,n);
cout <<"root->pocz: "<< tree.root->pocz <<endl; //prints 1
cout <<"root->pocz: "<< tree.root->pocz <<endl; //now prints sth like 2306050
return 0;
}
The main problem is that n points to w which is a local variable in the function insert. At the end of the function insert, w gets deleted automatically. And the pointer that is in the tree points to an empty location. At your first cout instruction, by chance, nothing did overwrite over the previous memory location of w. Therefore it prints 1. That memory location is then over written by something else (from the cout call) and therefore it prints garbage.
Now the solution, use Node *n = new Node; instead of setting it to &w.
In insertNode your w object has automatic storage and n is a pointer to it. In the call to that function, it will assign tree.root = n;. After the function returns the object is destroyed and the pointer tree.root is left dangling (points to deallocated memory). After that, dereferencing the dangling pointer such as tree.root->pocz will have undefined behaviour. You can fix that by allocating the Node dynamically.
I designed this code so that I can get a pointer of any position that user wants in a circular singly linked list, I am using cout to return pointer, I want such a mechanism that I can use it with my other function instead of re writing the whole code again, for that I need to do something with return type which is void right now
Here is the function ..
void pointer_to_node(int index){
Node*temptr;
temptr = new Node;
temptr = firstptr;
Node*temptr2;
temptr2 = new Node;
temptr2 = NULL;
int count = 1;
while (temptr!=temptr2){
if(count==index){
cout << "Required Pointer is : ";
cout<< temptr;}
count++;
temptr2=firstptr;
temptr=temptr->nextptr;
}
if (index>size_of_list())
{
temptr=NULL;
cout<< "Can't You think in bounds. Take your NULL Pointer ";
cout << temptr;
delete temptr;
delete temptr2;
}
}
You just need to return a Node *.
However, while you're doing that, you also really need to take out these: temptr = new Node; lines, as well as the deletes, as you're leaking memory there. You just immediately discard those new nodes by reassigning the pointers. The deletes at the end will delete the wrong nodes entirely, and aren't called in all cases anyway.
And if you pass an index of 0, your loop might take a very long time indeed.
I assume you have good reason for wanting to return NULL if you loop around the list.
Something like the following should suffice:
Node *pointer_to_node(int index)
{
Node *temp = firstptr;
while(index-- != 0) {
temp = temp->nextPtr;
if(temp == firstptr) return NULL;
}
return temp;
}
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