提问人:Apurv 提问时间:11/17/2023 最后编辑:273KApurv 更新时间:11/17/2023 访问量:87
为什么 ASAN 未将此问题报告为 stack-use-after-scope?
Why is this not reported as an issue by ASAN as 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;
答:
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_str
sub
在语句运行时,临时字符串已被销毁,但这已经无关紧要了,因为它仍然处于活动状态,并且包含来自临时对象的数据副本。cout
sub
评论
string sub(name.substr(0,4).c_str());
创建一个新字符串,您预计此处发生错误的位置?string sub(name.substr(0,4).c_str());
在作用域之后没有堆栈使用。因此,ASan 不会报告该范围之后的堆栈使用情况。getUser
返回一个临时值,如临时对象生存期所述,该值在完整表达式的末尾销毁。那是在,而不是中途。;
string