why is the address the same? [duplicate] - c++

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.

Related

Im losing elements in my dynamically allocated arrays

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.

Unexpected return value from main() function

I am working with doubly linked list. Every function operates well but at the end of main(), it stalls few seconds and return an unexpected random value.
At first I thought it was caused by the report() function, thus I put one more add() function at the end but nothing got fixed. I doubt it is a memory deallocating problem, but I don't see where some object got pre-deallocated.
(Compiled using Code::Blocks 17.12).
Here is my .cpp file (all in one):
#include <iostream>
using namespace std;
typedef struct element {
element(){
data = 0;
next = 0;
prev = 0;
}
~element(){
delete next;
delete prev;
cout << "element destructed" << endl;
}
int data;
element* next;
element* prev;
} elem;
typedef struct doublylinkedlist{
doublylinkedlist(){
head = 0; tail = 0;
}
~doublylinkedlist(){
while(head!=0) {
head = head->next;
delete head->prev;
}
delete tail;
cout << "list destructed" << endl;
}
elem* head;
elem* tail;
} doublyll;
doublyll ls;
void add(){
elem* temp = new elem;
cout << "Enter an integer: ";
cin >> temp->data;
if(ls.head == 0) {//empty
ls.head = new elem;
ls.head = temp;
} else{
if(ls.tail == 0){ //1-item list
ls.tail = new elem;
ls.tail = temp;
ls.head->next = ls.tail;
ls.tail->prev = ls.head;
}
else{
temp->prev = ls.tail;
ls.tail->next = temp;
ls.tail = temp;
}
}
}
void report(){
if(ls.head == 0) cout << "List is empty!" << endl;
else{
elem *temp = ls.head;
do{
cout << temp->data << endl;
temp = temp->next;
} while (temp != 0);
}
}
int main(){
report();
add();
add();
add();
report();
add();
return 0;
}
Could someone point out where the error comes from and how to fix it? I want the main() not to stall and return 0 as usual, not to the opposite.
This is the program when executed, this is my build message
First point: The elements will be deallocated by the class doublylinkedlist, so deallocating elements in the class element will cause double-deallocation.
Therefore, you should remove two delete statements from the destructior of the lass element.
~element(){
/* remove them */
//delete next;
//delete prev;
cout << "element destructed" << endl;
}
Second point: In the destructor of doublylinkedlist, head->prev is read after head = head->next; without checking if head is NULL.
head can be NULL by the assignment, so it should be checked.
~doublylinkedlist(){
while(head!=0) {
head = head->next;
if (head!=0) /* add this */
delete head->prev;
}
delete tail;
cout << "list destructed" << endl;
}
The last element will be deallocated by delete tail;, so this code looks tricky but should be OK.
Extra point: These code segments
ls.head = new elem;
ls.head = temp;
and
ls.tail = new elem;
ls.tail = temp;
are causing memory leaks by allocating elements and throwing them right away.
You should remove the extra allocations.
/* remove this */
//ls.head = new elem;
ls.head = temp;
and
/* remove this */
//ls.tail = new elem;
ls.tail = temp;
Unless you are using std::shared_ptr or similar constructs each object needs to have one other object which is it's owner and is responsible for deallocating it. Your code needs to have clear semantics for transferring ownership (e.g. a function createNode() would expect its caller to destroy the node).
In your code nodes are both deleted by the list and by each element. This means everything gets deleted twice (or more). In your particular case this is the sequence of events on destruction of doublylinkedlist:
doublylinkedlist deletes its first element.
The destructor of the first element deletes its previous element, this is null so has no effect
The destructor of the first element deletes its next element (the second element).
The destructor of the second element deletes its previous element (the first element)
The destructor of the first element deletes its previous element, this is null so has no effect
The destructor of the first element deletes its next element (the second element).
This infinite loop eventually causes a stack overflow. Note that this isn't guaranteed to be the exact sequence of events as deleting an object twice is undefined behaviour so potentially anything could happen.
The simple fix is to remove the element destructor and have the list be responsible for the lifetime of all elements.
You should also modify your doublylinkedlist destructor as it will attempt to dereference a null pointer on the last element, you also don't need to delete tail as it should have already been deleted. E.g:
~doublylinkedlist(){
while(head!=0) {
auto temp = head;
head = head->next;
delete temp;
}
}
You shoudl also make sure you obey the rule of three/five). One way of doing this is to make use of smart pointers, for example using unique_ptrs your code could look like this:
#include <iostream>
#include <memory>
using namespace std;
typedef struct element {
element() {
data = 0;
next = nullptr;
prev = nullptr;
}
~element() {
cout << "element destructed" << endl;
}
int data;
std::unique_ptr< element > next;
element* prev;
} elem;
typedef struct doublylinkedlist {
doublylinkedlist() {
head = 0; tail = 0;
}
~doublylinkedlist() {
std::cout << "list destructed\n";
}
std::unique_ptr< elem > head;
elem* tail;
} doublyll;
doublyll ls;
void add() {
std::unique_ptr<elem> temp(new elem());
cout << "Enter an integer: ";
cin >> temp->data;
if (ls.head == nullptr) {//empty
ls.head = std::move(temp);
}
else {
if (ls.tail == nullptr) { //1-item list
ls.head->next = std::move(temp);
ls.tail = ls.head->next.get();
ls.tail->prev = ls.head.get();
}
else {
temp->prev = ls.tail;
ls.tail->next = std::move(temp);
ls.tail = ls.tail->next.get();
}
}
}
void report() {
if (ls.head == 0) cout << "List is empty!" << endl;
else {
elem *temp = ls.head.get();
do {
cout << temp->data << endl;
temp = temp->next.get();
} while (temp != 0);
}
}
int main() {
report();
add();
add();
add();
report();
add();
return 0;
}
The ownership of elements is now explicit, the list owns head and head owns its next node which owns its next node etc. Destroying the list automatically destroys the first node which automatically destroys the second node etc. In this code you can actually omit the destructors completely. This should also help to prevent memory leaks, for example if you decide to add some error checking to add the unused temp element gets automatically deleted:
void add() {
std::unique_ptr<elem> temp(new elem());
cout << "Enter an integer: ";
cin >> temp->data;
if (!cin || temp->data > 100) {
cout << "invalid input value\n";
return; // temp is automatically deleted here
}
...
}

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;
}
}

Undefined action? Program prints out different values one after the other

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.

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.