问题
I'm using gcc and clang-embedded sanitizers for a little, including address sanitizer. And things work pretty well, but on next demo code I get no output related to a error despite it is there (to be more precise -- no output at all):
#include <string>
#include <iostream>
using std::string;
using std::cout;
class Foo
{
string _member;
public:
Foo(): _member("just a string") {}
const string& get() const { return _member; }
};
const string& bar()
{
// returning reference to a temp object on stack
return Foo().get();
}
int main()
{
cout << bar() << '\n';
return 0;
}
I tried g++ -O0 -g -fsanitize=address test.cc
and same with clang++
: g++-version just prints nothing, clang one prints garbage for a long time.
Valgrind on non-instrumented binary gives feedback:
Syscall param write(buf) points to unaddressable byte(s)
.
Is it internal asan problem or I'm doing something wrong?
Versions: gcc 4.9.2, clang 3.6.0
回答1:
Originally I thought that you face a use-after-return bug here on accessing temporary Foo object. UARs are not detected by ASan by default due to high memory overhead (see more details at dedicated wikipage).
But now I realized that situation is more complicated: std::string
may store input pointer as is (copy-on-write optimization), copy it to small buffer inside object (short string optimization) or in a new heap-allocated memory. The actual behavior depends on particular STL version that you are using (e.g. AFAIR libstdc++ implementation has recently changed).
I suggest you to report it to Asan's tracker to continue investigation there.
回答2:
#include <string>
#include <iostream>
using std::string;
using std::cout;
class Foo
{
string _member;
public:
Foo(): _member("just a string") {}
const string& get() const { return _member; }
};
const string bar()
{
// returning reference to a temp object on stack
return Foo().get();
}
int main()
{
cout << bar() << '\n';
return 0;
}
Works fine if you remove the reference.
Also the object you're creating is only valid in bar()
making it useless afterwards.
It works for your get method because the variable is pre existing in the scope of the class.
const string& bar()
{
const string a = Foo().get();
// returning reference to a temp object on stack
return a;
}
You will get a warning if you don't actually just return the reference but rather put it in a string for example:
main.cpp:23:12: warning: reference to stack memory associated with local variable 'a' returned [-Wreturn-stack-address]
What I can think of concerning your direct return statement is that the compiler already optimized it out.
来源:https://stackoverflow.com/questions/29656109/address-sanitizer-failure