指针被分配错误局部变量:C++返回局部变量指针输出异常问题
为什么返回局部变量指针后输出了意外的2002?
这个问题的核心是你不小心触发了C++里的未定义行为,咱们一步步拆解来看:
先看f1函数的问题
int* f1 (int n) { int* p = &n; return p; }
这里的n是f1的形参,属于局部变量,它的内存是分配在栈上的。当f1执行完毕返回时,栈上的这个局部变量会被销毁,对应的内存空间会被标记为「可重用」——注意,不是立刻清零,只是还给系统让后续函数调用时复用。
此时你返回的指针p,指向的是一块已经被释放的内存,这个指针就变成了野指针,后续对它的解引用操作完全不受C++标准的约束。
再梳理main函数的执行流程
- 调用
f1(101)时,栈上为n分配了空间,值是101,指针p指向它并返回给nn。但f1返回后,n的内存已经失效,nn成为野指针。 - 接着调用
f2(2002),f2的形参na和局部变量nb会占用栈上的空闲空间——刚好就复用了之前f1里n所在的那块内存(栈帧的复用是常见的内存管理方式)。于是na的值2002就被存在了原来n的位置。 - 当你执行
cout << *nn << endl;时,解引用野指针nn,刚好读到的是f2刚写入这块内存的2002——这完全是巧合,只是未定义行为的一种表现形式而已。
关于「未定义行为」的重要说明
C++标准对这种访问已释放内存的行为没有任何规定,程序可能输出101,可能输出2002,可能直接崩溃,甚至可能做完全无关的操作,每次运行结果都可能不一样。你用MinGW 6.2.0得到2002只是其中一种随机的结果,不能当成规律。
正确的解决方式
如果需要从函数返回数据,避免野指针问题可以用这些方法:
- 动态分配内存(记得用完释放,避免内存泄漏):
int* f1(int n) { int* p = new int(n); return p; } // main中调用后要释放内存 int main() { int* nn = f1(101); cout << *nn << endl; delete nn; // 必须释放 } - 让调用方提供指针参数:
void f1(int n, int* out) { *out = n; } // main中调用 int main() { int val; f1(101, &val); cout << val << endl; } - 直接返回值(最简单安全的方式,不需要指针):
int f1(int n) { return n; } // main中调用 int main() { int nn = f1(101); cout << nn << endl; }
内容的提问来源于stack exchange,提问作者NewOasis
相关产品推荐
相关产品推荐

