I’m learning C++, so I’m wrote a linked list implementation with some basic utilities. My insert function takes in a node pointer and iterates to the end of the list to append a newly initialized Node object, p. To my suprise, repeated calls to the insert method appear to share node p!? Thus after many invocations, insert will assign p->next to itself, inducing an infinite loop.
#include <iostream>
#include <string>
using namespace std;
struct Node {
Node *next;
int val;
};
void insert(Node *n, int val) {
Node * cur = n;
while (cur->next) {
cout << "Val " << cur->val << "\n";
cur = cur->next;
}
Node p = {0, val};
cur->next = &p;
}
int main() {
Node n1;
n1.val = 1;
insert(&n1, 2);
insert(&n1, 3);
insert(&n1, 4);
return 0;
}
I ran this through gdb to look at what is going on in insert. Indeed, in the second call to insert I found that p was already initialized before executing Node p = {0, val}; and that future calls preserved the same value of p->next despite explicitly setting it to 0. I seem to have a gap in my understanding because translating this into C produces the same bug. I was only able to fix with malloc which is not what I want.
Why does it occur? p is allocated onto the stack per invocation no?
>Solution :
After insert function returns, local variables cur and p are destroyed and that memory space is available for reuse. You are not allowed to access a variable after it is destroyed, not even with a pointer, because the memory space can be reused for something else.
As you see this is not just a theoretical possibility but actually happens, all the time. If you just call the exact same function again it’s quite likely that you’ll get the exact same memory arrangement so the variable p the second time will use the exact same memory space it used the first time. If you call a different function like printf (or cout <<) instead of insert, you might find that space is overwritten with some of the variables inside printf.
This is why every single linked list tutorial tells you to use malloc. Apart from global variables, it’s basically the only way to create some variable that isn’t deleted when the function returns. A "variable" created by malloc isn’t ever deleted until you free it. (It also has no name, so pointers are the only way to use that variable and this fact seems to confuse many people.)