【发布时间】:2013-08-08 17:30:45
【问题描述】:
我有一个不应该工作的代码,但它可以工作。你能告诉我为什么吗?
#include <iostream>
void f ( int** a, int b ) ;
int main (void) {
int ** a ;
a = new int* () ;
f(a,5) ;
std::cout << **a << std::endl ;
return 1 ;
}
void f ( int** a, int b ) {
*a = &b ;
}
我声明了一个指向名为a 的指针,我为其分配一个指针,然后将它传递给f()。另一个f() 参数是一个常量字面量,因此它应该没有在main() 中分配静态内存,因此它不应该存在于f() 之后。在f() 内部,我将局部变量b 的内存方向分配给f() 复制的main 上的指针,然后当main() 执行f() 时,所有局部变量都应该被删除然后继续,所以@ 987654332@ 应该指向垃圾,或者什么都没有,但它没有并指向 5,已经删除的值强>b。
真正发生了什么?为什么这段代码有效?
【问题讨论】:
-
它调用未定义的行为,未定义的行为是未定义的。
-
当他们说这是一种未定义的行为时,这意味着它可以通过正确的行为让你大吃一惊,或者有时它不会奏效。
-
它不起作用;它具有未定义的行为。当您销毁它包含的对象时,内存不一定会消失,因此悬空指针可能(或可能不会)仍然看到曾经存在的值。如果启用它们,您应该会收到编译器警告。
-
@MikeSeymour 我正在使用 -Wall -pedantic 进行编译,编译器不会抱怨。我应该使用哪些标志。
-
@GonzoRI:实际上,也许你不会收到警告。大多数流行的编译器都会诊断
return &b;,但可能是*a的赋值超出了编译器的分析能力。