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

为何ASAN未检测到stack-use-after-scope问题?附C++代码疑问

关于Address Sanitizer的stack-use-after-scope问题疑问

第一段代码及理解疑问

我无法理解Address Sanitizer的stack-use-after-scope概念,以下是我的代码:

#include <iostream>
using namespace std;
class User {
        public:
        User(){
                _name = "No Name";
        }
        User(string name){
                _name = name;
                _salary = 0;
        }

        string getName(){
                return _name;
        }

        int* getRoles(){
                return _roles;
        }
        private:
        string _name;
        int _salary;
        int _roles[5];
};

class Employee {
        public:
        Employee(User user){
                _user = user;
        }

        User getUser(){
                return _user;
        }
        private:
        User _user;

};
int main() {
        // your code goes here

        User user("User1");
        Employee employee(user);

        auto roles = employee.getUser().getRoles();
        roles[0] = 1;
}

我的理解是:getUser()返回的临时对象会被销毁,roles变量可能指向已被回收的内存地址,这个理解是否正确?

代码对比疑问

类似地,以下代码会触发错误:

string name = "name123";
auto arr = name.substr(0,4).c_str();
cout<<arr[0];

但为何这段代码却不会报错?

string name = "name123";
string sub(name.substr(0,4).c_str());
cout<<sub;

同时,为何第一段代码未被ASAN检测为stack-use-after-scope问题?


问题解答

1. 第一段代码的理解是否正确?

你的理解完全正确。employee.getUser()返回的是User类型的临时对象,这个对象的生命周期只持续到当前表达式结束(也就是auto roles = ...;这一行执行完)。getRoles()返回的是临时对象中_roles数组的地址,当临时对象被销毁后,roles就指向了栈上已被回收的内存区域,后续对roles[0]的赋值操作本质就是stack-use-after-scope问题。

2. 为什么第二段代码触发错误,第三段却不会?

  • 第二段代码中,name.substr(0,4)返回的临时string对象会在表达式结束后立即销毁,c_str()得到的是这个临时对象内部字符数组的地址,临时对象销毁后该内存被回收,访问arr[0]就是操作已释放的栈内存,ASAN会检测到这个问题。
  • 第三段代码中,临时string对象销毁前,我们已经用它的c_str()构造了新的string sub。string的构造函数会把c_str()指向的字符内容完整复制到自己管理的内存空间中,后续使用的是sub自身的内存,和原临时对象无关,因此不会出现悬空引用。

3. 为什么第一段代码没被ASAN检测出来?

ASAN对栈内存的检测存在一定局限性:

  • 临时对象销毁后,栈上对应的内存区域可能还没被ASAN标记为“不可访问”,或者未被其他数据覆盖,此时的内存操作可能刚好避开了检测逻辑。
  • 栈内存的标记和复用机制存在延迟,当你对roles[0]赋值时,该区域可能还处于ASAN未监控的状态。
  • 可以尝试关闭编译优化(添加-O0参数)、使用更高版本的编译器,或者增加对该内存的后续访问操作,ASAN大概率能检测到这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 01:52:52