Address sanitizer failure

心已入冬 提交于 2019-12-12 04:56:33

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!