繁体   English   中英

解决消毒剂故障

[英]Address sanitizer failure

我正在使用gcc和嵌入了clang的消毒器,包括地址消毒器。 一切正常,但是在下一个演示代码中,尽管有错误,但我没有得到与错误相关的输出(更确切地说,根本没有输出):

#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;
}

我试过了g++ -O0 -g -fsanitize=address test.cc ,与clang++相同:g ++-version只输出任何内容,clang一个版本打印了很长时间。 非仪器二进制文件上的Valgrind给出反馈: Syscall param write(buf) points to unaddressable byte(s)

是内部存在的问题还是我做错了什么?

版本:gcc 4.9.2,clang 3.6.0

最初,我认为您在访问临时Foo对象时会遇到返回后使用错误。 由于内存开销高,默认情况下ASan不会检测到UAR(请参阅专用 wikipage上的更多详细信息)。

但是现在我意识到情况更加复杂: std::string可以按原样存储输入指针(写时复制优化),将其复制到对象内部的小缓冲区(短字符串优化)或新的堆分配内存中。 实际行为取决于您使用的特定STL版本(例如,AFAIR libstdc ++实现最近已更改)。

我建议您将其报告给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;
}

如果删除引用,效果很好。

同样,您要创建的对象仅在bar()有效,此后它就无用了。

它适用于您的get方法,因为该变量在类的范围内是预先存在的。


const string& bar()
{
    const string a = Foo().get();

    // returning reference to a temp object on stack
    return a;
}

如果您实际上不只是返回引用而是将其放在字符串中,则将收到警告:

main.cpp:23:12: warning: reference to stack memory associated with local variable 'a' returned [-Wreturn-stack-address]

我能想到的关于您的直接返回语句的原因是编译器已经对其进行了优化。

暂无
暂无

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

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