我在学习指南中发现了这个问题,我不确定为什么返回指向局部变量/参数的指针会很糟糕。有什么想法吗?
答案 0 :(得分:6)
这不是一个“坏习惯”(暗示可能导致问题),而是绝对导致未定义行为的做法。这就像解除引用空指针一样:不要这样做,并期望你的程序在逻辑限制范围内运行。
说明:
当声明局部变量(包括参数)时,它被赋予自动存储,这意味着编译器负责为变量分配内存,然后在不花费任何努力的情况下释放该内存。程序员的一部分。
void foo(int bar)
{
int baz;
} //baz and bar dissappear here
当变量'lifetime终止时(例如函数返回时),编译器履行其承诺,并且销毁函数本地的所有自动变量。这意味着任何指向这些变量的指针现在指向程序认为“免费”执行任何操作的垃圾内存。
返回值时,这不是问题:程序找到一个新位置来放置值。
int foo(int bar)
{
int baz = 6;
return baz + bar; //baz + bar copied to new memory location outside of foo
} //baz and bar disapear
返回指针时,指针的值将照常复制。但是,指针仍指向同一位置,现在是垃圾:
int* foo(int bar)
{
int baz = 6;
baz += bar;
return &baz; //(&baz) copied to new memory location outside of foo
} //baz and bar disapear! &baz is now garbage memory!
访问此内存是不明确的行为,因此您的程序几乎肯定会以某种方式行为不端。例如,我曾经fell victim to this exact problem,当我的程序没有崩溃或终止时,我的变量开始降级为垃圾值,因为编译器覆盖了“免费”内存。
答案 1 :(得分:2)
因为 将 导致程序中出现未定义的行为。
答案 2 :(得分:2)
如果在函数返回后返回指向局部变量的指针,则它超出范围。 从那时起,如果您访问返回的指针,则它是未定义的行为。
答案 3 :(得分:2)
函数返回后,堆栈中的局部变量和参数已被解除分配。他们可能仍然存在,但是没有保证,当某些东西决定使用堆栈时,他们肯定会受到打击。
使用WP中的图表:
顶部的堆栈指针是可以安全地分配和放置新变量的位置(例如调用函数时)。当函数(例如DrawLine)返回时,它们会从堆栈中取出(堆栈指针只是递增,因此它不再指向超出范围的绿色变量)。以后出现的任何事情以及分配和使用堆栈空间都会破坏旧值。
答案 4 :(得分:1)
局部变量存储在堆栈中。存储在堆栈中的值会在函数/代码块退出时被销毁(即,到达函数的末尾 - 从技术上讲,它们可以持续更长时间,但这是另一个讨论)。因此,指针(指向存储器中特定位置的地址)指向可能不再存在的值。
答案 5 :(得分:0)
因为该变量的地址属于创建它的堆栈帧。没有其他的。一旦return
,该激活记录就会被清除,之前的任何内容现在都是未定义的。