使用动态内存避免引用失效失败,触发heap-use-after-free错误
原代码错误原因与修正后代码分析
一、原代码触发错误的核心原因
看原函数f()的实现:
vector<int>& f() { vector<int> a = *new vector<int>{15, 15, 16}; return a; }
这里存在两个致命问题:
- 悬垂引用:
a是栈上的局部vector对象,它通过拷贝构造把new出来的堆vector内容复制到自身。函数退出时,栈上的a会被自动销毁,此时返回的引用指向的是已经失效的栈内存,属于典型的悬垂引用。 - 内存泄漏+非法内存操作:
new出来的堆vector没有被保存指针,直接丢失导致内存泄漏;而main里的delete &b本质是试图释放栈内存,这是未定义行为,直接触发了AddressSanitizer检测到的堆内存非法访问错误。
当main里用b这个悬垂引用遍历元素时,访问的是已经被销毁的栈对象内存,必然触发内存错误。
二、修正后的代码是否正确?
修正后的函数实现:
vector<int>& f() { vector<int>& a = *new vector<int>{15, 15, 16}; return a; }
这段代码是合法且可正确运行的:
a是堆上vector对象的引用,函数退出时堆对象不会被销毁,返回的引用始终有效。main中接收引用后,遍历访问元素的操作正常;最后delete &b也正确释放了堆上的vector对象,不存在内存泄漏。
额外建议
虽然修正后的代码能正常工作,但手动管理堆内存+返回引用的写法风险极高——一旦遗漏delete操作就会造成内存泄漏。更推荐用智能指针自动管理内存,比如:
unique_ptr<vector<int>> f() { return make_unique<vector<int>>({15, 15, 16}); } int main() { auto b = f(); for (auto x : *b) { cout << x << endl; } // 无需手动delete,智能指针会自动释放内存 cout << "finished" << endl; }
内容的提问来源于stack exchange,提问作者JohnZ
相关产品推荐
相关产品推荐

