【问题标题】:Object still accessible after std::unique_ptr goes out of scope. Differing runtime behaviours在 std::unique_ptr 超出范围后仍可访问对象。不同的运行时行为
【发布时间】:2014-05-29 23:10:48
【问题描述】:

以下代码将一个指向Entry 类型对象的指针传递给函数modify_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 版(tags/RELEASE_34/final)

目标:x86_64-apple-darwin13.1.0

线程模型:posix

它运行没有错误,输出是

约翰的构造函数

在 modify_entry() 内部

John Doe 的析构函数

从 modify_entry() 返回

约翰·多伊

Here,但是,由于第 25 行,我收到了运行时错误。

问:为什么我运行clang生成的可执行文件没有运行时错误?

如果有人能澄清情况,我将不胜感激。请注意,我并没有尝试正确转让所有权。这个错误代码的人为示例是调试过程的副产品。 make_uniqueunique_ptr 等的移动语义很棒,但这不是我要问的。

提前致谢。

【问题讨论】:

  • 阅读this question,尤其是接受的答案。
  • @Angew 谢谢。当然,我在发布我的问题之前搜索了类似的问题,但标签有时可能会产生误导。我明白你的意思,但不幸的是,我无法阅读接受的答案;它以一个比喻开头……

标签: c++ c++11 unique-ptr dangling-pointer


【解决方案1】:

问:为什么运行clang生成的可执行文件没有运行时错误?

因为未定义的行为是未定义的。程序在其生命周期结束后尝试访问对象。 C++ 没有为此类程序定义任何行为。

make_uniqueunique_ptr 等的移动语义非常棒,这样的事情只是您应该使用它们的另一个原因。

【讨论】:

  • 同意这个,不能依赖未初始化内存的差异。
【解决方案2】:

因为你正在做的是undefined behavior,所以在main 函数中你使用一个指向被破坏对象的指针。

对象被破坏(删除),但您仍然有一个指向它所在位置的指针,取消引用该指针会导致未定义的行为。

【讨论】:

    【解决方案3】:

    但是,指针指向的对象似乎在函数返回后仍然存在。

    这里的关键是“似乎”。实际上,Entry 的生命周期在这一行的末尾结束:

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

    unique_ptr 获得了内存的所有权,但临时的unique_ptr 的生命周期在该语句的末尾结束,因此它也会删除它拥有的Entry。访问对象以前使用的内存是未定义的行为。它适用于某些平台而不适用于其他平台只是未定义行为的本质。

    【讨论】:

      猜你喜欢
      • 2011-01-31
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      • 1970-01-01
      • 1970-01-01
      • 2016-10-14
      相关资源
      最近更新 更多