Please refer the code given here:
This code is a part of stack implementation in C++:
Code 1:
void Stack::pop()
{
if (top != 0) {
node* temp = top;
top = top -> link;
delete temp;
}
}
Code 2:
void Stack::pop()
{
if (top != 0) {
node* temp = new node;
temp = top;
top = top -> link;
delete temp;
}
}
In first example, I didn't use new, while I did use it in second one. On running, both give same output with the complete program, which can be found below:
#include <iostream>
using namespace std;
struct node {
string name;
node* link;
};
class Stack
{
node* top;
public:
Stack();
void push(string s);
void pop();
void display();
~Stack(){}
};
Stack::Stack() {
top = 0;
}
void Stack::push(string s)
{
node* temp = new node;
temp -> name = s;
temp -> link = top;
top = temp;
}
void Stack::pop() // Function in question
{
if (top != 0) {
node* temp = new node;
temp = top;
top = top -> link;
delete temp;
}
}
void Stack::display()
{
node* temp = new node;
temp = top;
while (temp != 0)
{
cout << temp -> name << "\n";
temp = temp -> link;
}
}
int main() {
Stack s;
s.push("Ra");
s.push("Sa");
s.push("Ga");
s.pop();
s.display();
}
What is the difference in using and not using new pointer here?
Also does the memory automatically free itself or do I have to do it in destructor? If so, how to do it?
There's memory leak in the 2nd code snippet, even though it looks working well. new node is meaningless for node* temp = new node;, because temp is assigned to top at once. Then the original memory address created by new node is lost and couldn't be deleted again.
Also does the memory automatically free itself or do I have to do it in destructor?
Each object newed has to be deleted by yourself. Consider about smart pointers, they will manage such things for you.
In these lines:
node* temp = new node;
temp = top;
you allocate new node, store it in temp variable and ton the next variable store in the same variable another pointer. So that new node is lost and newer used. node* temp = new node; has no effect other than leaking memory.
Also does the memory automatically free itself or do I have to do it
in destructor?
No. Memory is not freed automatically. And you nearly never actually call object destructor manually.
If so, how to do it?
The old way is to use delete. But im modern C++ you should not use naked owning pointers and really should consider using std::unique_ptr.
While using new/allocating the memory, you are causing a memory leak.
node* temp = new node;
temp = top; //temp is now pointing to a new memory location.
//Thus the memory allocated by in the previous code line gets leaked
Code1 is the correct way to do it. Code 2 causes memory leak.
You have to delete the memory that you allocate using the delete operator in the destructor.
Stack::~Stack()
{
while(NULL != top)
{
node* temp = top;
top = top->link;
delete temp;
}
}
A smart pointer Solution. You will need c++11 compiler for the following code to compile/work.
#include <iostream>
#include <memory>
using namespace std;
struct node {
string name;
std::unique_ptr<node> link;
};
typedef std::unique_ptr<node> node_ptr;
class Stack
{
node_ptr top;
public:
Stack();
void push(string s);
void pop();
void display();
~Stack(){}
};
Stack::Stack() {
}
void Stack::push(string s)
{
auto temp = std::make_unique<node>();
temp -> name = s;
temp -> link = top;
top = temp;
}
void Stack::pop()
{
if (top != null) {
top = top -> link;
}
}
void Stack::display() const
{
node* temp = top.get();
while (temp != 0)
{
cout << temp -> name << "\n";
temp = (temp -> link).get();
}
}
int main() {
Stack s;
s.push("Ra");
s.push("Sa");
s.push("Ga");
s.pop();
s.display();
}
Related
I'm creating my first linked list and I have found something weird, in my main function whenever I call printf() the start pointer which points to the first node in my linked list shows that the data is garbage and the next pointer is a very random address, unlike if I didn't use printf() it seems good and all nodes are created and all good!
#include <iostream>
int node_counter = 0;
struct node
{
int data;
node* next;
};
node* start;
void creat_ll()
{
node n1;
start = &n1;
n1.data = 0;
n1.next = NULL;
node_counter++;
}
void insertNode(int x)
{
node* ptr = start;
while (ptr->next != NULL)
{
ptr = ptr ->next;
}
node* temp = ptr;
ptr = new(node);
ptr->data = x;
ptr->next = NULL;
printf("node number: %d\n",x);
temp->next = ptr;
node_counter++;
}
int main()
{
creat_ll();
insertNode(10);
insertNode(20);
// printf("number of nodes = %d \n", node_counter);
insertNode(30);
printf("test\n");
printf("number of nodes = %d \n", node_counter);
insertNode(40);
insertNode(50);
insertNode(60);
insertNode(70);
printf("number of nodes = %d \n", node_counter);
}
As people mentioned in the comments, the problem is not related to printf(), but to dangling pointers. In the local scope of creat_ll(), you've created a variable node n1 (allocated on the stack) and then assigned the address of n1 to start, which has global scope. Once the creat_ll() function exits, everything in the scope of creat_ll() is gone, including n1. So in main(), start points to deleted data.
This, of course, would be solved if you allocate all your variables on the heap (i.e. use keywords new and delete). On the heap, you can create or delete variables from anywhere and they'll stick around until you delete them (or until your program exits). If you allocate n1 on the heap, the memory survives even after create_ll() exits. However, with this, you take on the responsibility of managing the underlying memory yourself, meaning that once you're done with your list, something has to go back and delete all the nodes; otherwise, the nodes stick around and you end up with a memory leak.
Cherno has a great video on object lifetime that you can find here: https://youtu.be/iNuTwvD6ciI. At 4:30, he shows an example that is nearly identical to yours.
So a better overall implementation is to create a class that handles all of this. We should be able to create a linked list, add nodes to it (allocate memory), remove nodes from it (delete memory), and, once we're done with it, delete all memory associated with the linked list.
Below is an example implementation. I'll leave the implementation of the remove() method to you.
#include <cstdio>
struct node
{
int data;
node* next;
};
class LinkedList
{
public:
LinkedList() = default;
// Add x to the end of the list.
void push_back(const int value)
{
if (root == nullptr)
{
root = new node{ };
root->data = value;
root->next = nullptr;
}
else
{
node* ptr { root };
while (ptr->next != nullptr)
{
ptr = ptr->next;
}
node* const newNode { new node{ } };
newNode->data = value;
newNode->next = nullptr;
ptr->next = newNode;
}
++size;
}
// Remove the first occurrence of x.
void remove(const int value)
{
// left as an exercise
}
void printList() const
{
std::printf("Number of nodes: %lu\n", size);
const node* ptr { root };
while (ptr != nullptr)
{
std::printf("%d ", ptr->data);
ptr = ptr->next;
}
std::printf("\n");
}
~LinkedList()
{
const node* ptr { root };
while (ptr != nullptr)
{
const node* const next { ptr->next };
delete ptr;
ptr = next;
}
size = 0;
}
private:
node* root { nullptr };
std::size_t size { 0 };
};
int main()
{
LinkedList ll { LinkedList{ } };
ll.push_back(10);
ll.push_back(20);
ll.printList();
ll.push_back(30);
ll.push_back(40);
ll.printList();
}
Output:
Number of nodes: 2
10 20
Number of nodes: 4
10 20 30 40
EDIT: Here is a minimal example of memory getting overridden due to the stack getting popped. Note that this behavior is undefined, so depending on the compiler you're using, you may see some output or get a segfault. I'm using gcc and I get the output shown below.
#include <iostream>
#include <string>
std::string* s;
void createString()
{
std::string local_string = "This string is about to get popped out of the stack.";
s = &local_string;
std::cout << *s << std::endl;
}
int main()
{
createString();
std::cout << *s << std::endl;
return 0;
}
Output 1
This string is about to get popped out of the stack.
0D8Vbout to get popped out of the stack.
Output 2
This string is about to get popped out of the stack.
Ubout to get popped out of the stack.
Output 3
This string is about to get popped out of the stack.
tUbout to get popped out of the stack.
I need help in understanding why my Linked List approach doesn't work as expected.
#include <iostream>
using namespace std;
class Node {
public:
int Data;
Node* Next;
Node(int data) {
Data = data;
Next = NULL;
}
};
void insertNodeAtEnd(Node* HEAD, int data) {
Node* it = HEAD;
if (HEAD == NULL) { HEAD = new Node(data); }
else {
while (it->Next != NULL) { it = it -> Next; }
it -> Next = new Node(data);
}
}
void printLinkedList(Node* HEAD) {
Node* it = HEAD;
while (it != NULL) {
cout << it->Data << endl;
it = it -> Next;
}
}
int main() {
Node* HEAD = NULL;
// Node* HEAD = new Node(0);
insertNodeAtEnd(HEAD, 5);
insertNodeAtEnd(HEAD, 2);
insertNodeAtEnd(HEAD, 10);
printLinkedList(HEAD);
return 0;
}
The above main() function does NOT work (ie: no output, and the HEAD keeps resetting to NULL as soon as the control leaves insertNodeAtEnd()), and I've found similar questions here on SO which explain that this is because the pointer is being passed by value, and that makes partial sense to me.
Why does it work as expected when I replace Node* HEAD = NULL; with Node* HEAD = new Node(0); in the main() function, if the pointer is being passed as value?
How are nodes getting added if I initialise HEAD like Node* HEAD = new Node(0);, but not in the case where HEAD = NULL initially? I was able to get it to work properly by using pointer to pointer but I can't understand why this approach doesn't work. I am sorry if I haven't explained my question properly, please let me know if any clarification is required.
The underlying issue can be reduced to this code:
void insertNodeAtEnd(Node* HEAD, int data) {
//...
if (HEAD == NULL) { HEAD = new Node(data); }
//...
}
int main() {
Node* HEAD = NULL;
insertNodeAtEnd(HEAD, 5);
//...
You seem to assume that assigning to HEAD inside insertNodeAtEnd would change the HEAD variable inside of main. This is not true. Your pointer is passed by value, so the address is copied for the function. Changing this copied variable will not change the value of HEAD inside of main.
To fix this you could pass a pointer to a pointer instead, like this:
void insertNodeAtEnd(Node** HEAD, int data) {
//...
if (*HEAD == NULL) { *HEAD = new Node(data); }
//...
}
int main() {
Node* HEAD = NULL;
insertNodeAtEnd(&HEAD, 5);
//...
This pointer to a pointer is still passed by value, however the pointer that it points to will be the same as the on from main.
The problem come from your first insertion. You change the value of head which is reset when you quit the function. You can only change the value behind the pointer, not the pointer itself.
A solution for this would be to pass a pointer of pointer. Something like: (not tested)
void insertNodeAtEnd(Node** HEAD, int data) {
if (*HEAD == NULL) { *HEAD = new Node(data); }
else {
Node* it = *HEAD;
while (it->Next != NULL) { it = it -> Next; }
it -> Next = new Node(data);
}
}
int main() {
Node* HEAD = NULL;
// Node* HEAD = new Node(0);
insertNodeAtEnd(&HEAD, 5);
return 0;
}
As you don't change the pointer of pointer but only the value behind it (the actuual pointer to head) the change will be keep once you exit the function.
The answer has already been given by #Brotcrunsher. I am posting to help you implement a better solution, that separates the concept of a list and an element of a list, that incapsulates the methods used and that frees the resources it uses, when it goes out of scope:
#include <iostream>
using namespace std;
class Node {
public:
int Data;
Node* Next;
Node(int data = 0) {
Data = data;
Next = nullptr;
}
};
class List {
public:
Node* Head = nullptr;
void Insert(int data) {
if (Head == nullptr)
Head = new Node(data);
else {
Node* ptr;
for (ptr = Head; ptr->Next != nullptr; ptr = ptr->Next)
;
ptr->Next = new Node(data);
}
}
void Print() {
for (Node* ptr = Head; ptr != nullptr; ptr = ptr->Next)
cout << ptr->Data << endl;
}
~List() {
Node* ptr = Head;
while (ptr != nullptr) {
Node* tmp = ptr;
ptr = ptr->Next;
delete tmp;
}
}
};
int main() {
List list;
list.Insert(5);
list.Insert(2);
list.Insert(10);
list.Print();
return 0;
}
Hi i am frankly new to these forums so i tried looking up as much as i could but i couldn't find anything relate-able to my problem.
I am trying to read nodes that i stored into a file and insert them into a linked list that i created
THE insert functions works perfectly fine however while loading it when i attempt to insert the node ,
1.it inserts the node
2.reads the new node
3.since im using a pointer , the pointer now points to the new read node
4.inserts the newly read node from the file into the list overwriting the old data.
This causes my old data to be completely lost and the new node to act as the header of the file
load function :
void load_file_students(linked_student &students)
{
node_student *test = new node_student;
ifstream stu_list("students.dat",ios::binary);
stu_list.read((char*)test, sizeof(*test));
while (!stu_list.eof())
{
//students.insert_node_list(test);
students.insert_node_list(test);
stu_list.read((char*)test, sizeof(*test));
}
stu_list.close();
}
the insert_node function:
void linked_student::insert_node_list(node_student *student)
{
node_student* temp = new node_student;
temp = student;
if (head == NULL)
{
head = temp;
}
else
{
node_student *ptr = this->head;
while (ptr->next != 0)
{
ptr = ptr->next;
}
temp->previous = ptr;
ptr->next= temp;
}
}
the node :
#pragma once
#include <string>
using namespace std;
static int roll_number = 1; // used for the personal identification of the student
class node_student
{
public:
bool fees_paid = true;
string name;
float CGPA;
int ID; // same as the static roll_number provided
int semester;
string department;
string elective_subjects[5];
node_student *next;
node_student *previous;
node_student();
~node_student();
};
during debugging mode it is evident that when i re-read the data in the load function during
stu_list.read((char*)test, sizeof(*test));
it overwrites the old data in the insert function as well even though it is called before this line.
Once again the insertion into the file works perfectly fine , i can actually see the values being loaded via the debugging mode
here is the insert function for reference
INSERT :
void update_student_file(linked_student testing)
{
node_student *temp = testing.head;
ofstream stu_list("students.dat",ios::binary);
while (temp != NULL)
{
stu_list.write((char*)temp, sizeof(*temp));
temp = temp->next;
}
stu_list.close();
}
Here a fix to load_file_students:
void load_file_students(linked_student &students)
{
node_student test; //way use dynamic allocation?
ifstream stu_list("students.dat",ios::binary);
while (stu_list.read((char*)test, sizeof(*test)))
{
students.insert_node_list(&test);
}
//file will be closed at the destructor.
}
Another fix for insert_node_list
void linked_student::insert_node_list(node_student *student)
{
node_student* temp = new node_student;
*temp = *student; //call copy constructor, do not copy pointer value.
if (head == NULL)
{
head = temp;
}
else
{
node_student *ptr = this->head;
while (ptr->next != 0)
{
ptr = ptr->next;
}
temp->previous = ptr;
ptr->next= temp;
}
}
I have been working on a linked list problem, using two pointers to the head and the tail of the list respectively. The issue I have is the following:
When I want to remove from the front or the back of the list, I get memory leaks when the corresponding class methods are implemented using temporary dynamically allocated node pointer and I can't find out what exactly is the problem that is causing the leak.
#include <iostream>
class Node {
public:
Node():data(0),ptrNode(nullptr){};
~Node() {};
// declaring the getters and setters
float getData() const {return data;};
void setData(float d) {data = d;};
Node* getNodePtr() const {return ptrNode;};
void setNodePtr(Node* n){ptrNode = n;};
private:
float data;
Node* ptrNode;
};
class List {
private:
Node * ptrHead;
Node * ptrTail;
public:
List():ptrHead(nullptr),ptrTail(nullptr) {};
~List() {};
void insertAtFront(float x) {
Node * temp = new Node();
temp->setData(x);
if (ptrHead == nullptr) {
ptrHead = temp;
ptrTail = temp;
} else {
temp->setNodePtr(ptrHead);
ptrHead = temp;
}
};
void insertAtBack(float x) {
Node * temp = new Node();
temp->setData(x);
if (ptrHead == nullptr) {
ptrHead = temp;
ptrTail = temp;
} else {
ptrTail->setNodePtr(temp);
ptrTail = temp;
}
};
void removeFromFront() {
if (ptrHead==nullptr) { // if list is empty
std::cout << "List is already empty" << std::endl;
return;
}
if (ptrHead==ptrTail) { // if list has one element
delete ptrHead;
ptrHead = nullptr;
ptrTail = nullptr;
return;
}
// assign current Head to temp, assign next node to head
// delete temp
Node * temp = new Node();
temp = ptrHead;
ptrHead = ptrHead->getNodePtr();
delete temp;
temp = nullptr;
};
void removeFromBack() {
if (ptrHead==nullptr) { // if list is empty
std::cout << "List is already empty" << std::endl;
return;
}
if (ptrHead==ptrTail) { // if list has one element
delete ptrHead;
ptrHead = nullptr;
ptrTail = nullptr;
return;
}
// create two temp Node pointers for this one
Node * sec2last = new Node();
Node * last = new Node();
sec2last = ptrHead;
last = ptrTail;
// locate second to last element and assign it to sec2last
while (sec2last->getNodePtr() != ptrTail) {
sec2last = sec2last->getNodePtr();
}
ptrTail = sec2last;
ptrTail->setNodePtr(nullptr);
delete last;
delete sec2last;
last = nullptr;
sec2last = nullptr;
};
};
I run the following in main():
// global function that dynamically allocates memory in its scope
// for a linked list
void generateList(int x) {
if (x<=0) {
cout << "Give a positive integer!" << endl;
return;
}
List * aList = new List();
for (int i = 0;i<x;i++) {
aList->insertAtFront(i+1);
}
aList->removeFromBack(); // this causes leaks
delete aList;
}
// MAIN
int main() {
for (int i = 0;i<80000000;i++)
generateList(1); // just repeatedly generate dynamic list
// with one element
return 0;
}
I should point out that if we don't use dynamically allocate memory for the temporary nodes within the removeFromFront() and removeFromBack() methods, then the program works fine. But, like I said, It kills me that I can't see why we have leaks with the code above.
Thanks!
Node * temp = new Node();
temp = ptrHead;
This is a memory leak right here. You allocate a new Node and store a pointer to it in temp. Then you overwrite that pointer and leak the node you just allocated.
// create two temp Node pointers for this one
Node * sec2last = new Node();
Node * last = new Node();
sec2last = ptrHead;
last = ptrTail;
And here you do it again. Why are you allocating new Nodes here?
I'm implementing a stack with a linked list for review. My pop function isn't working correctly. I created a test with the nodes in main doing the exact same thing my linkedList function is doing but I'm getting a segmentation fault ever time time. Here is the code.
#include <iostream>
struct Node{
int data;
Node* next;
};
class Stack{
private:
Node head;
int size;
public:
Stack();
~Stack();
int getSize();
void push(int val);
int pop();
void printStack();
};
Stack::Stack(){
head.data = 0;
head.next = NULL;
}
Stack::~Stack(){
}
int Stack::getSize(){
return size;
}
void Stack::push(int val){
Node newNode;
newNode.data = val;
if(size == 0) newNode.next = NULL;
else newNode.next = head.next;
head.next = &newNode;
size++;
}
int Stack::pop(){
int returnVal = head.next->data;
head.next = head.next->next;
return returnVal;
}
}
int main(){
Stack s;
s.push(8);
s.push(30);
s.push(40);
int value = s.pop();
int value2 = s.pop(); //segmentation fault
std::cout<<value<<"\n"<<value2<<"\n";
/* This works correctly
Node head;
head.data = 0;
head.next = NULL;
Node n1;
n1.data = 5;
n1.next = NULL;
head.next = &n1;
Node n2;
n2.data = 8;
n2.next = head.next;
head.next = &n2;
Node n3;
n3.data = 30;
n3.next = head.next;
head.next = &n3;
int value = head.next->data;
std::cout << value << "\n";
head.next = head.next->next;
value = head.next->data;
std::cout << value << "\n";
*/
return 1;
}
The problem is how you create the Node. In your case you create a local variable, which only exists within the scope of the function push(). You could use something like this.
void Stack::push(int val){
Node* newNode = new Node;
newNode->data = val;
/* ... */
}
Edit: added a version of the stack (by no means complete)
#include <iostream>
struct Node{
int data;
Node* next;
};
class Stack {
private:
Node* head;
int size;
public:
Stack();
~Stack();
int getSize();
void push(int val);
int pop();
void printStack();
};
Stack::Stack() : head(0), size(0)
{
}
Stack::~Stack(){
}
int Stack::getSize(){
return size;
}
void Stack::push(int val){
Node* newNode = new Node;
newNode->data = val;
newNode->next = head;
head = newNode;
size++;
}
int Stack::pop(){
if(head != 0)
{
int val = head->data;
Node* tmp = head;
head = head->next;
tmp->next = NULL;
delete tmp;
size--;
return val;
}
else
{
return -1; // what happens if stack is empty ?
}
}
void Stack::push(int val){
Node newNode;
newNode is declared to be a local object in automatic scope of the push() function.
Which means that when push() returns, this object is going to get automatically destroyed. That's what "automatic scope" means.
The code in push() attempts to insert this object into your stack, and assumes that this object will exist after push() returns. This, of course, isn't true, and this ends up corrupting memory, resulting in undefined behavior.
This is not how object lifetime and scope works, fundamentally, in C++.
I think both your push() and pop() methods have problems. You can try using these versions:
// create new node, point it to current head, and then assign it as new head
void Stack::push(int val){
Node* newNode = new Node;
newNode->data = val;
newNode->next = head; // OK even if head == NULL
head = newNode;
size++;
}
// retrieve value from head (if it exists), pop the head and return the value
int Stack::pop(){
if (head == NULL) return -1; // -1 indicates empty stack
int returnVal = head->data; // get popped value
Node* temp = &head;
head = head->next; // pop the top of the stack
delete temp;
size--;
return returnVal;
}
There's a problem in your code for push, actually:
void Stack::push(int val){
Node newNode;
newNode.data = val;
if(size == 0) newNode.next = NULL;
else newNode.next = head.next;
head.next = &newNode;
size++;
}
When you write
Node newNode;
you're declaring the Node object with automatic storage duration (you sometimes hear this called "on the stack"). This Node only exists as long as the push function is running, and as soon as the function returns the node ceases to exist. Trying to use that node later results in undefined behavior, which in practice could be anything from an outright crash to reading back garbage data.
To address this issue, you'll need to use dynamic allocation. Create the node using new Node and store a pointer to it. Objects created this way live until something explicitly destroys them, which means that they'll live after the push call finishes. You'll then need to adjust pop to deallocate the memory.