Ошибка дезинфицирующего устройства адреса

Я немного использую встроенные дезинфицирующие средства 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++- версия просто ничего не печатает, лягушка один печатает мусор долгое время. Valgrind на неинструментированном бинарном файле дает обратную связь:Syscall param write(buf) points to unaddressable byte(s),

Это внутренняя проблема асана или я делаю что-то не так?

Версии: gcc 4.9.2, clang 3.6.0

2 ответа

Первоначально я думал, что вы сталкиваетесь здесь с ошибкой использования после возврата при доступе к временному объекту Foo. UAR не распознаются ASan по умолчанию из-за больших накладных расходов памяти (подробности см. На специальной вики-странице).

Но теперь я понял, что ситуация более сложная: std::string может хранить входной указатель как есть (оптимизация копирования при записи), копировать его в небольшой буфер внутри объекта (оптимизация короткой строки) или в новую выделенную кучу память. Реальное поведение зависит от конкретной используемой версии STL (например, реализация AFAIR libstdC++ недавно изменилась).

Я предлагаю вам сообщить об этом следопыту Асана, чтобы продолжить расследование там.

#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]

Что касается вашего прямого оператора return, я могу думать о том, что компилятор уже оптимизировал его.

Другие вопросы по тегам