You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++调用返回指针的函数后连续两次printf输出异常是什么原因?

核心问题本质
  • 你遇到的所有异常本质上是触发了C/C++的未定义行为(UB),根源有两个:一是add2函数返回了栈上局部变量的指针,二是第二个printf调用的格式符和传参数量不匹配

1. 返回局部变量指针的问题

函数内部定义的非静态局部变量是分配在栈内存上的,函数执行结束后,对应的栈帧会被操作系统回收,这块内存的内容可以被后续的其他函数调用随意覆盖。你的add2函数里的c是局部变量,函数结束后&c指向的内存已经失效,此时z2是野指针,任何对*z2的访问都是未定义行为,输出什么结果都有可能。

2. 不同写法结果差异的原因

  • 连续两次调用printf的场景:第一次调用printf的时候,会在栈上开辟自己的栈帧空间,直接覆盖了之前add2函数存c的那块内存,此时解引用z2拿到的是printf执行后留下的垃圾值,所以输出随机大数。另外你写的printf("%d\n%d\n", *z2);要求2个int类型参数,你只传了1个,参数不匹配本身也属于未定义行为,会进一步加剧输出异常。
  • 同一printf输出的场景:调用printf之前还没有其他函数调用覆盖那块失效的栈内存,*z2刚好能拿到之前的计算值,而且参数一次性压入栈中,所以看起来输出正常,但这只是未定义行为的巧合,换编译器、换编译配置、甚至换运行时机都可能出问题。
  • 连续输出z1正常的场景:z1是main函数的局部变量,main函数执行结束前它对应的栈内存一直有效,而且你存储的是值本身,不是指向其他失效内存的指针,所以访问完全合法。

正确的实现方案

如果你确实需要返回指针类型的结果,可以选择以下两种安全的写法:

  • 写法1:在堆上分配内存存储结果,堆内存不会随函数结束自动回收,记得用完后手动释放避免内存泄漏:
int* add2(int* a, int* b) {
    int* c = (int*)malloc(sizeof(int));
    *c = *a + *b;
    return c;
}
// main函数使用完z2后加一行 free(z2); 释放内存
  • 写法2:由外层调用方传入结果变量的地址,函数内部直接写入结果:
void add2(int* a, int* b, int* res) {
    *res = *a + *b;
}
// main中调用方式:
int z2;
add2(&x, &y, &z2);

如果没有必须返回指针的需求,直接用你写的第一个返回值的add函数是最安全高效的写法。


内容的提问来源于stack exchange,提问作者Quang Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 01:09:03