有人可以帮我理解这个C程序有什么问题吗?
#include <stdio.h>
#include <stdlib.h>
struct Box {
int **value;
};
void nop(void) {
/* Why does this function have side effects? */
void *a = malloc(sizeof *a);
free(a);
}
struct Box *makeBox(void) {
int *value = NULL;
struct Box *box = malloc(sizeof *box);
box->value = &value;
return box;
}
int main(void) {
struct Box *box = makeBox();
printf("Dereferenced: %p\n", *box->value);
nop();
printf("Dereferenced: %p\n", *box->value);
}
如果我运行它,它会打印:
Dereferenced: (nil)
Dereferenced: 0x562831863727
但是,如果我注释掉nop
函数,我会得到:
Dereferenced: (nil)
Dereferenced: (nil)
有人可以帮我理解为什么调用nop
更改*box->value
?
答案 0 :(得分:2)
您的程序有未定义的行为。 box->value
内的main
指针包含不确定的值。在makeBox
内部,它曾指向本地变量value
,但现在makeBox
已完成,并且该局部变量已经消失。尝试将其取消引用为*box->value
会导致未定义的行为。这就是你观察到的。
答案 1 :(得分:2)
基本上nop()
函数只是因为使用堆栈而产生“副作用”。问题出在makeBox()
函数中,该函数设置指向堆栈变量的指针。我在代码段中添加了一些评论:
struct Box *makeBox(void) {
// value is an integer pointer on the stack
int *value = NULL;
struct Box *box = malloc(sizeof *box);
// box->value is set to the address of the stack location of value
box->value = &value;
return box;
}
当nop()
在堆栈上分配a
时,它基本上是在你的另一个指针所在的堆栈上踩踏。这是一个为什么你不能返回指向堆栈变量的指针的例子,因为它不会在分配它的函数范围之外持久存在。