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

Я немного использую встроенные дезинфицирующие средства 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

0

Решение

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

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

Я предлагаю вам сообщить об этом Трекер асана продолжить расследование там.

1

Другие решения

#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, я могу думать о том, что компилятор уже оптимизировал его.

0

По вопросам рекламы [email protected]