#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-传递给遍历函数后,该值会随机丢失,即使在所有其他调用之后似乎已正确分配了该值。
答案 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));
}
*newnode
是Node*
,因此必须是
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)