简体   繁体   English

我不了解指针,地址和范围

[英]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 ,例如: 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. 但是在B.3,我希望它也返回值42,但不会。 I assume 2686700 refers to some address in the memory. 我假设2686700指向内存中的某个地址。

#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; 如果采用if (root == 0)分支,则root将指向struct point newRoot; which is allocated on the stack inside the body of the if branch. 这是在if分支主体内部的堆栈上分配的。 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; newRoot结构在离开分支的主体和函数的主体之后(在您的情况下,在return value;之后)超出范围return value; statement. 声明。 However, the global pointer variable root will keep pointing to that location in memory (on stack). 但是,全局指针变量root将继续指向内存中的该位置(堆栈上)。 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. 该位置上的堆栈存储器的内容很可能会被其他一些代码覆盖,因此从该位置读取point (成员)值(例如,通过root指针)将导致不确定的行为,这就是为什么要得到这种结果的原因。

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). 别忘了设置next指针,因为默认情况下它不会为NULL (除非也许不是malloc而是使用calloc来对返回的内存进行零初始化,从而在大多数平台上有效地使next的值等于NULL )。 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 . 另外,不要忘记释放动态分配的任何内存:使用malloccallocrealloc分配的任何内存都必须稍后使用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. 问题在于,一旦函数到达}关闭if语句, root就会失效。 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: 幸运的是,解决此问题的方法很简单:使用malloc而不是newRoot为链表元素分配内存:

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. 当然,在退出程序之前,您需要使用malloc free分配的malloc ,以避免内存泄漏。

You create struct point newRoot; 您创建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. 此后,任何使用其指针( *root )的操作都应给出未定义的结果。

You must understand that stuff on the stack disappears when it goes out of scope 您必须了解,堆栈超出范围时,堆栈中的内容会消失

SO 所以

root = &newRoot;

Here newRoot is on the stack. 这里newRoot在堆栈中。 End of function - End of newRoot - So the pointer is invalid 函数结束newRoot结束-指针无效

Use malloc to create the newRoot object so I can live longer that the function call 使用malloc创建newRoot对象,这样我可以使函数调用的寿命更长

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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