Following is a code snippet, I have written and I am currently struggling with my print-outs.
In my main method I call the function insertPoint
twice with valid input, for example: insertPoint(42); insertPoint(56);
insertPoint(42); insertPoint(56);
and get the following output:
A.1 42
B.3 2686700
At B.3 however I would expect it to also return the value 42, but it doesn't. I assume 2686700 refers to some address in the memory.
#include <stdio.h>
#include <stdlib.h>
struct point {
int value;
struct point* next;
};
struct point *root;
int insertPoint(int value) {
// Graph is empty, set new root
if(root == 0){
struct point newRoot;
newRoot.value = value;
root = &newRoot;
(*root).value = value;
printf("A.1 %d \n", (*root).value); // "A.1 42"
return value;
}
printf("B.3 %d \n", (*root).value); // "B.3 2686700"
/* rest of code here; irrelevant since related variables are not changed */
}
Does someone have an idea why this happens? Any constructive comment/answer is appreciated.
I would also appreciate, if the downvoters would provide me feedback, why they found my question inappropriate.
If the if (root == 0)
branch is taken, root
will point to struct point newRoot;
which is allocated on the stack inside the body of the if
branch. The newRoot
structure goes out of scope after leaving the body of the branch and the body of the function, in your case after the return value;
statement. However, the global pointer variable root
will keep pointing to that location in memory (on stack). The contents of stack memory at that location will most likely be overwritten by some other code, hence reading a point
(member) value from that location (eg via the root
pointer) will result in undefined behaviour, which is why you get such results.
You probably meant to dynamically allocate the new root, eg:
if(root == 0) {
root = (point *) malloc(sizeof(point));
root->value = value;
root->next = NULL;
printf("A.1 %d \n", root->value); // "A.1 42"
return value;
}
Don't forget to set the next
pointer, as it will not by default be NULL
(unless perhaps instead of malloc
you use calloc
which zero-initializes the returned memory, effectively making the value of next
equal to NULL
on most platforms). Additionally, don't forget to deallocate any memory you allocate dynamically: any memory allocate with malloc
, calloc
or realloc
must be deallocated later using free
.
Your code has undefined behavior because it lets a pointer to local variable be used outside the scope.
It happens here:
struct point newRoot;
...
root = &newRoot;
The problem with this is that once the function reaches the }
closing the if
statement, root
becomes invalid. Any dereference of it is undefined behavior. Hence when you do this
printf("B.3 %d \n", (*root).value);
you access memory pointed to by an invalid pointer.
Fortunately, the fix to this problem is simple: use malloc
instead of newRoot
to allocate memory for the linked list element:
if(root == 0){
root = malloc(sizeof(struct point));
root->value = value;
printf("A.1 %d \n", (*root).value); // "A.1 42"
return value;
}
Of course you would need to free
the memory you allocate with malloc
before exiting the program in order to avoid memory leaks.
You create struct point newRoot;
on stack inside a function. Since, it is on stack, it is destroyed on exit from this function. Any use of its pointer ( *root
) should give undefined result after that.
You must understand that stuff on the stack disappears when it goes out of scope
SO
root = &newRoot;
Here newRoot
is on the stack. End of function - End of newRoot
- So the pointer is invalid
Use malloc
to create the newRoot
object so I can live longer that the function call
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.