The following code passes to the function modify_entry a pointer to an object of type Entry and inside the body of the function a unique_ptr adopts the raw pointer. However, the object to which the pointers point seems to live on after the function returns.

When I compile this code

#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;
    
}

with

clang version 3.4 (tags/RELEASE_34/final)

Target: x86_64-apple-darwin13.1.0

Thread model: posix

It runs without an error and the output is

Constructor for John

Inside modify_entry()

Destructor for John Doe

Back from modify_entry()

John Doe

Here, however, I get a runtime error because of line 25.

Q: Why isn't there a runtime error when I run the executable generated by clang?

I would really appreciate it if someone could clarify the situation. Please note that I am not trying to properly transfer ownership. This contrived example of bad code is the byproduct of a debugging process. make_unique and move semantics for unique_ptr etc are great, but this is not what I am asking.

Thanks in advance.

有帮助吗?

解决方案

However, the object to which the pointers point seems to live on after the function returns.

The key thing here is "seems to". Actually, the Entry's lifetime ends at the end of this line:

 std::unique_ptr<Entry>{e_ptr}->name_ += " Doe";

The unique_ptr has taken ownership of the memory, but the temporary unique_ptr's lifetime ends at the end of that statement, so it also deletes the Entry that it owns. Accessing memory that was formerly used by the object is undefined behavior. That it works on some platforms and not others is just the nature of undefined behavior.

其他提示

Q: Why isn't there a runtime error when I run the executable generated by clang?

Because undefined behaviour is undefined. The program tries to access an object after its lifetime is over. C++ defines no behaviour for such programs.

make_unique and move semantics for unique_ptr etc are great, and things like this are just yet another reason they are what you should be using.

Because what you are doing is undefined behavior, when in the main function you use a pointer to a destructed object.

The object is destructed (deleted), but you still have a pointer to where it was, dereferencing this pointer is what leads to the undefined behavior.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top