Следующий код переходит к функции modify_entry
указатель на объект типа Entry
и внутри тела функции а unique_ptr
принимает необработанный указатель. Однако объект, на который указывают указатели, кажется, продолжает жить после возврата из функции.
Когда я компилирую этот код
#include <iostream>
#include <memory>
struct Entry {
Entry(std::string name) : name_(name) { std::cout << "Constructor for " + name_ + '\n'; }
~Entry() { std::cout << "Destructor for " + name_ + '\n'; }
std::string name_;
};
void modify_entry(Entry* e_ptr){
std::cout << "Inside modify_entry()\n";
std::unique_ptr<Entry>{e_ptr}->name_ += " Doe";
}
int main(int argc, const char * argv[])
{
Entry* entry_ptr = new Entry("John");
modify_entry(entry_ptr);
std::cout << "Back from modify_entry()\n";
std::cout << entry_ptr->name_ << '\n'; // <---- line 25
return 0;
}
с
Clang версия 3.4 (теги / RELEASE_34 / финал)
Цель: x86_64-apple-darwin13.1.0
Модель потока: posix
Он работает без ошибок и вывод
Конструктор для Джона
Внутри modify_entry ()
Разрушитель для Джона Доу
Вернуться из modify_entry ()
Джон Доу
Вот, однако, я получаю ошибку во время выполнения из-за строки 25.
Q: Почему нет ошибки времени выполнения, когда я запускаю исполняемый файл, сгенерированный clang?
Буду очень признателен, если кто-то сможет прояснить ситуацию. Обратите внимание, что я не пытаюсь правильно передать право собственности. это надуманный пример плохого кода является побочным продуктом процесса отладки. make_unique
и переместить семантику для unique_ptr
и т. д. отлично, но это не то, что я спрашиваю.
Заранее спасибо.
Однако объект, на который указывают указатели, кажется, продолжает жить после возврата из функции.
Ключевым моментом здесь является «кажется». На самом деле, Entry
Срок жизни заканчивается в конце этой строки:
std::unique_ptr<Entry>{e_ptr}->name_ += " Doe";
unique_ptr
завладела памятью, но временная unique_ptr
время жизни заканчивается в конце этого оператора, поэтому он также удаляет Entry
что он владеет. Доступ к памяти, которая ранее использовалась объектом, является неопределенным поведением. То, что он работает на некоторых платформах, а не на других, это просто природа неопределенного поведения.
В: Почему при запуске исполняемого файла, созданного clang, не возникает ошибка времени выполнения?
Потому что неопределенное поведение не определено. Программа пытается получить доступ к объекту после окончания срока его службы. C ++ не определяет поведение для таких программ.
make_unique
и переместить семантику для unique_ptr
и т. д. это здорово, и подобные вещи — это еще одна причина, по которой вы должны использовать это.
Потому что ты делаешь это неопределенное поведение, когда в main
Функция, которую вы используете указатель на разрушенный объект.
Предмет является уничтожен (удален), но у вас все еще есть указатель на то, где он было, разыменование этого указателя приводит к неопределенному поведению.