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

116 Views Asked by At

I am not able to understand the concept behind 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;
}

Here from what I understand getUser returns a temporary object that might be destroyed and the roles variable might point to a loation already reclaimed. Is that understanding correct?

Similarly the folowing code gives error.

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

But why not this?

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

There are 1 best solutions below

0
On BEST ANSWER

Temporary objects persist until the end of the full expression in which they're created. A full expression is an expression that isn't part of another expression, so basically until the next ;.

That means that in this snippet

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

arr is a pointer to the array owned by the temporary object returned by substr. Since that object gets destroyed at the end of the full expression in which it's created, it no longer exists when you attempt to read from it in the next statement.


In this statement

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

The array pointed to by the pointer returned by c_str continues to exist until the end of the full expression. That means it's still alive when sub's constructor accesses it to copy its contents.

The temporary string has been destroyed by the time the cout statement runs, but that doesn't matter anymore, since sub is still alive and contains a copy of the data from the temporary object.