返回临时对象指针的代码为何可运行?如何触发错误?
问题解答
1. 是否属于未定义行为?
这绝对是未定义行为。函数get_str()里的QByteArray arr是局部对象,函数执行完毕返回时,该局部对象会被销毁,它管理的内存空间也会被释放。而arr.constData()返回的指针恰好指向这片已释放的内存,后续在main()中通过指针访问这片内存,完全属于访问无效内存的非法操作。
之所以编译运行看似“正常”,只是因为栈上的这片内存暂时没被其他数据覆盖,属于纯粹的运气,绝非代码本身合法。
2. 如何触发错误?
可以通过以下几种方式让问题暴露:
- 覆盖栈内存:在
main()中获取指针后,插入占用栈空间的操作,比如定义大数组、调用其他函数,把原局部对象占用的栈内存覆盖:
此时运行大概率会输出乱码或直接崩溃。int main() { const char *s = get_str(); char buf[100] = {0}; // 覆盖栈上原arr的内存 printf("%s\n", s); return 0; } - 开启编译器严格检查与优化:在Qt Creator的编译选项中,开启
-O2及以上优化级别,同时添加-Wall -Wextra -Wreturn-local-addr警告参数。编译器会直接检测到返回局部对象指针的问题,给出警告甚至报错,优化后的程序也会直接触发内存访问错误。 - 重复调用函数:在
main()中多次调用get_str(),让栈上的旧内存被反复覆盖,后续访问指针时必然会出现异常。
3. 直接使用printf("%s\n", get_str());能否规避问题?
不能。不管是把指针存入变量还是直接作为参数传递给printf,本质逻辑完全一致:get_str()执行完毕后,局部的QByteArray arr已被销毁,返回的指针指向的内存已经失效。printf读取该指针时,依然是在访问无效内存,属于未定义行为。只是某些场景下内存没被立刻覆盖,看起来“正常”,但风险始终存在。
内容的提问来源于stack exchange,提问作者KcFnMi
相关产品推荐
相关产品推荐

