简体   繁体   English

函数调用后指针值丢失 - C.

[英]Pointer value being lost after function call - C

#include <stdlib.h>
#include <stdio.h>

typedef struct Node
{
    int *data;
}Node;


void AllocateNode(Node **newnode)
{
    *newnode = malloc(sizeof(int));
}


void insert(Node **p2head, int *p2data)
{
    if(*p2head == NULL)
    {
        AllocateNode(p2head);
        (**p2head).data = p2data;
    }
}

void ReadAll(Node **headptr)
{
    int x = 10;
    insert(headptr, &x);
}

void traverse(Node *headptr)
{
    printf("%d\n",*(headptr->data));
}

int main(void)
{
    Node *ListHead;
    ListHead = NULL;
    ReadAll(&ListHead);
    printf("%d\n",*(ListHead->data));

    traverse(ListHead);
}

I am very confused because 我很困惑,因为

printf("%d\n",*(ListHead->data));

outputs: 10 - the desired value, however 输出:10 - 所需的值

printf("%d\n",*(headptr->data));

outputs: 0 - the value is randomly lost after being passed to the traverse function, even though it seems to be assigned correctly after all the other calls. 输出:0 - 该值在传递给遍历函数后随机丢失,即使它似乎在所有其他调用之后正确分配。

An pointer to non-static local variable is passed from ReadAll() to insert() and it is saved to the newly created node. 指向非静态局部变量的指针从ReadAll()传递到insert()并将其保存到新创建的节点。

This variable becomes unavailable after returning from ReadAll() and dereferencing the pointer after that invokes undefined behavior . ReadAll()返回后,此变量变为不可用,并在调用未定义的行为后取消引用指针。 This is the cause of randomness. 这是随机性的原因。

To avoid this, the pointer to put on the node should be that points to object that is available even after returning from ReadAll() . 为避免这种情况,放在节点上的指针应指向即使从ReadAll()返回后仍可用的对象。

This can be archived by dynamically allocating 这可以通过动态分配来存档

void ReadAll(Node **headptr)
{
    int *x = malloc(sizeof(int));
    *x = 10;
    insert(headptr, x);
}

or making the variable static. 或使变量静态。

void ReadAll(Node **headptr)
{
    static int x = 10;
    insert(headptr, &x);
}

Also, the implementation of Allocate() is wrong as Peter pointed out. 此外,正如Peter指出的那样, Allocate()的实现是错误的。 The allocation size should be sizeof(Node) , not sizeof(int) . 分配大小应为sizeof(Node) ,而不是sizeof(int)

There are several problems in your code : 您的代码中存在几个问题:

In

void AllocateNode(Node **newnode)
{
    *newnode = malloc(sizeof(int));
}

*newnode is a Node* so it must be *newnodeNode*所以它必须是

void AllocateNode(Node **newnode)
{
    *newnode = malloc(sizeof(Node));
}

In

void ReadAll(Node **headptr)
{
    int x = 10;
    insert(headptr, &x);
}

you give the address of x being a local variable to save it in the Node. 您将x的地址作为局部变量以将其保存在节点中。

All access through that pointer is invalid and has an unspecified behavior when you exit ReadAll 当您退出ReadAll时,通过该指针的所有访问都是无效的并且具有未指定的行为

One possibility is to allocate the int 一种可能性是分配int

void ReadAll(Node **headptr)
{
    int * x = malloc(sizeof(int));

    *x = 10;
    insert(headptr, x);
}

After these corrections, compilation and execution : 经过这些更正,编译和执行:

vxl15036 /tmp % gcc -pedantic -Wextra -g l.c
vxl15036 /tmp % ./a.out
10
10

Execution under valgrind valgrind下执行

vxl15036 /tmp % valgrind ./a.out
==28709== Memcheck, a memory error detector
==28709== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==28709== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==28709== Command: ./a.out
==28709== 
10
10
==28709== 
==28709== HEAP SUMMARY:
==28709==     in use at exit: 12 bytes in 2 blocks
==28709==   total heap usage: 2 allocs, 0 frees, 12 bytes allocated
==28709== 
==28709== LEAK SUMMARY:
==28709==    definitely lost: 8 bytes in 1 blocks
==28709==    indirectly lost: 4 bytes in 1 blocks
==28709==      possibly lost: 0 bytes in 0 blocks
==28709==    still reachable: 0 bytes in 0 blocks
==28709==         suppressed: 0 bytes in 0 blocks
==28709== Rerun with --leak-check=full to see details of leaked memory
==28709== 
==28709== For counts of detected and suppressed errors, rerun with: -v
==28709== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)

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

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