为什么 ASAN 未将此问题报告为 stack-use-after-scope?

Why is this not reported as an issue by ASAN as stack-use-after-scope?

提问人:Apurv 提问时间:11/17/2023 最后编辑:273KApurv 更新时间:11/17/2023 访问量:87

问:

我无法理解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;
C++ 地址清理器

评论

3赞 UnholySheep 11/17/2023
string sub(name.substr(0,4).c_str());创建一个新字符串,您预计此处发生错误的位置?
2赞 Eljay 11/17/2023
string sub(name.substr(0,4).c_str());在作用域之后没有堆栈使用因此,ASan 不会报告该范围之后的堆栈使用情况。
2赞 Useless 11/17/2023
getUser返回一个临时值,如临时对象生存期所述,该值在完整表达式的末尾销毁。那是在,而不是中途。;
0赞 Apurv 11/17/2023
我假设name.substr(0,4);会返回一个临时对象,它的生命周期是在对象初始化后还是之前结束?是因为临时对象贯穿整个表达式吗?
0赞 Useless 11/17/2023
它是另一个临时的,所以它也活到完整表达的末尾——也就是说,直到构建完毕后它才会被销毁。string

答:

6赞 Miles Budnek 11/17/2023 #1

临时对象将一直持续到创建它们的完整表达式结束。完整表达式是不属于另一个表达式的表达式,因此基本上直到下一个 .;

这意味着在此代码段中

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

arr是指向 返回的临时对象所拥有的数组的指针。由于该对象在创建它的完整表达式的末尾被销毁,因此当您在下一个语句中尝试从中读取该对象时,该对象将不再存在。substr


在此声明中

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

返回的指针指向的数组将继续存在,直到完整表达式结束。这意味着当 的构造函数访问它以复制其内容时,它仍然处于活动状态。c_strsub

在语句运行时,临时字符串已被销毁,但这已经无关紧要了,因为它仍然处于活动状态,并且包含来自临时对象的数据副本。coutsub