我无法理解 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;
临时对象会一直保留到创建它们的完整表达式结束为止。完整表达式是不属于另一个表达式的表达式,所以基本上直到下一个
;
。
这意味着在这个片段中
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
仍然存在,并且包含临时对象中数据的副本。