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

时间:2019-03-04 09:40:13

标签: c pointers parameters

#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);
}

我很困惑,因为

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

输出:10-但是,所需的值

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

输出:0-传递给遍历函数后,该值会随机丢失,即使在所有其他调用之后似乎已正确分配了该值。

2 个答案:

答案 0 :(得分:1)

指向非静态局部变量的指针从ReadAll()传递到insert(),并保存到新创建的节点。

ReadAll()返回并在调用未定义行为之后取消对指针的引用后,此变量变得不可用。这是随机性的原因。

为避免这种情况,放置在节点上的指针应该指向即使从ReadAll()返回后仍然可用的对象。

可以通过动态分配将其存档

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

或将变量设为静态。

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

同样,彼得指出,Allocate()的实现是错误的。 分配大小应为sizeof(Node),而不是sizeof(int)

答案 1 :(得分:0)

您的代码中有几个问题:

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

*newnodeNode*,因此必须是

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

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

您将 x 的地址作为本地变量保存到节点中。

通过该指针的所有访问均无效,并且在退出 ReadAll

时具有未指定的行为

一种可能是分配 int

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

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

这些更正之后,进行编译和执行:

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

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)