简体   繁体   English

解决消毒剂故障

[英]Address sanitizer failure

I'm using gcc and clang-embedded sanitizers for a little, including address sanitizer. 我正在使用gcc和嵌入了clang的消毒器,包括地址消毒器。 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. 我试过了g++ -O0 -g -fsanitize=address test.cc ,与clang++相同:g ++-version只输出任何内容,clang一个版本打印了很长时间。 Valgrind on non-instrumented binary gives feedback: Syscall param write(buf) points to unaddressable byte(s) . 非仪器二进制文件上的Valgrind给出反馈: 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 版本:gcc 4.9.2,clang 3.6.0

Originally I thought that you face a use-after-return bug here on accessing temporary Foo object. 最初,我认为您在访问临时Foo对象时会遇到返回后使用错误。 UARs are not detected by ASan by default due to high memory overhead (see more details at dedicated wikipage ). 由于内存开销高,默认情况下ASan不会检测到UAR(请参阅专用 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. 但是现在我意识到情况更加复杂: std::string可以按原样存储输入指针(写时复制优化),将其复制到对象内部的小缓冲区(短字符串优化)或新的堆分配内存中。 The actual behavior depends on particular STL version that you are using (eg AFAIR libstdc++ implementation has recently changed). 实际行为取决于您使用的特定STL版本(例如,AFAIR libstdc ++实现最近已更改)。

I suggest you to report it to Asan's tracker to continue investigation there. 我建议您将其报告给Asan的跟踪器,以便在那里继续调查。

#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. 同样,您要创建的对象仅在bar()有效,此后它就无用了。

It works for your get method because the variable is pre existing in the scope of the class. 它适用于您的get方法,因为该变量在类的范围内是预先存在的。


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. 我能想到的关于您的直接返回语句的原因是编译器已经对其进行了优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM