2013-06-06 2 views
1
std::unique_ptr<std::string> foo_ptr(new std::string("foo")); 
foo_ptr.reset(foo_ptr.get()); 
std::cout << *foo_ptr << std::endl; //prints "foo" so obj hasn't been deleted 
//runtime error: "pointer being freed was not allocated" 

Почему я получаю ошибку времени выполнения, и это просто совпадение, которое распечатывает «foo»?Simple unique_ptr issue

+3

Это неопределенное поведение. Все может случиться. Программа перестала быть действующей программой на линии №: 3. –

+1

Да, это совпадение. На самом деле это носовой демон. –

+0

Кстати: лучший способ узнать, что что-то было разрушено, - это создать класс, который печатает что-то на его деструкторе. –

ответ

7

Цитата из n3376 20.7.1.2.5/4 и 5.

Эффектов: присваивают р сохраненного указателя, а затем, если старое значение сохраненного указателя, old_p, не было равно nullptr, вызывает get_deleter() (old_p).

[Примечание: порядок этих операций значителен , потому что вызов get_deleter() может уничтожить * это. - примечание конца)

Таким образом, разыменование этого указателя приводит к неопределенному поведению.

Постусловия: get() == p. [Примечание: постусловие не выполняется, если вызов get_deleter() уничтожает * this, так как this-> get() больше не является допустимым выражением. - примечание конца)

3
foo_ptr.reset(foo_ptr.get()); 

Эта линия будет «свободный» текущий указатель в foo_ptr, и установите его на значение foo_ptr.get(). Поскольку foo_ptr.get() извлекается до того, как значение обновляется, оно указывает на старое место.

Не делайте этого. Это приводит к неопределенному поведению. Вы никогда не должны звонить reset с тем же значением, что и у него.

+1

Вы уверены, что он «первым освобождает, а затем устанавливает»? (Ответ ForEveR указывает, что он «сначала устанавливает, а затем освобождает»). – 7cows

+0

@ 7cows: ForEveR прав на заказ (стандарт говорит так), но он не меняет конечного результата. Единственный случай, когда порядок имеет значение, - если деструктор старого объекта выбрасывает (что в любом случае является крайне плохой практикой). – syam

+2

Концептуально, он освобождает указатель, который он имеет в настоящее время, и устанавливает значение для переданного. Точно, в каком порядке это происходит, на самом деле не является точкой моего ответа. –