简体   繁体   中英

I don't understand pointers, addresses and scopes

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM