Следующая программа вылетает с ошибкой glibc double free:
#include <iostream>
#include <memory>
class foo {
public:
foo()
{
std::cout << "foo constructed" << std::endl;
}
~foo()
{
std::cout << "foo destructed" << std::endl;
}
};
int main() {
auto f = std::make_shared< foo >();
std::cout << "Before reset" << std::endl;
f.reset( f.get() );
std::cout << "After reset" << std::endl;
return 0;
}
Из этого я получаю следующий вывод (за которым следует ошибка glibc):
foo constructed
Before reset
foo destructed
After reset
foo destructed
Итак, очевидно, что в этом случае объект уничтожается дважды. Один раз по сбросу и один раз по std::shared_ptr
выходит за рамки. На самом деле это то, чего я ожидал.
Вкл. cppreference , однако я нахожу следующий текст (находится по адресу http://en.cppreference.com/w/cpp/memory/shared_ptr/reset):
Если * он уже владеет объектом и является последним shared_ptr, владеющим им, объект уничтожается посредством принадлежащего ему средства удаления, если ptr не является указателем на него.
По-моему, это фактически говорит о том, что объект не должен быть уничтожен, как в моем примере. Довольно удивительно, но если стандарт так говорит. Я что-то не так понимаю, или имеющаяся у меня реализация std::shared_ptr
не соответствует стандарту?
Для тех, кто спрашивает, почему я это делаю:
В настоящее время я пытаюсь выяснить, как временно управлять голыми указателями на объекты, созданные с помощью new
и new[]
. Идея состоит в том, чтобы использовать std::shared_ptr::reset()
для замены средства удаления на неиспользуемое средство удаления. Альтернатива - обернуть код блоком try { stuff() } catch( ... ) { delete x; throw;}
.