【问题标题】:Does erasing a shared_ptr from a set deletes the managed object从集合中删除 shared_ptr 是否会删除托管对象
【发布时间】:2015-06-21 13:35:04
【问题描述】:

在下面的代码中,我希望指针tr 指向的内存被销毁。然而,即使我验证了sp1,指向与tr 相同的地址,并且清除集合会导致trial 对象sp 一直被销毁,tr 仍然指向相同的地址和@987654327根据gdb,它显示的@对象没有被破坏,在return 0行。

class trial
:public enable_shared_from_this<trial>
{
public:
    trial(int n)
    {
        cout<<"new trial created with number : " << n << endl;
        a = (int*)malloc(4);
        *a = n;
    }


    ~trial() {
        cout << "trial destroyed"<< endl;
    }

    int *a;
};

int main() {
    cout << "Program Started" << endl;

    trial *tr = new trial(5);
    shared_ptr<trial> sp1(tr);
    set<shared_ptr<trial>> trialVector;

    trialVector.insert(std::move(sp1));


    trialVector.clear();

    return 0;
}

当程序到达return 0这一行时,控制台显示:

Program Started
new trial created with number : 5
trial destroyed

承认,一旦 sp1 从集合中删除,tr 确实被破坏了。但是 tr 仍然有相同的地址和相同的值。

这是怎么回事?

编辑:为了清楚起见,我的问题是:

指针tr 显示的地址的内容是否应该被删除,一旦指向管理器对象的最后一个shared_ptr 指向指针tr 的地址,在从集合中删除时被破坏?

【问题讨论】:

  • 我不明白到底是什么问题?好像没问题。
  • 如何确定“对象没有被破坏”?析构函数运行后,检查该内存地址中剩余内容的内容本质上是没有意义的 - 对象已死。
  • 因为在调试器中,我可以看到它显示了相同的地址,并且该地址仍然有相同的试验对象,其中a的值为5。
  • tr 现在是一个悬空指针 - 一旦您将控制权传递给 shared_ptr,依靠保持有效的原始原始指针是有风险的,因为 shared_ptr 现在负责它的寿命。简而言之,一旦 shared_ptr 被销毁,取消引用 tr 是未定义的行为。
  • 未定义,这意味着 C++ 标准没有定义访问未分配内存时会发生什么。任何事情都可能发生,包括它仍然看起来像一个有效的对象。

标签: c++ shared-ptr move-semantics


【解决方案1】:

对象被销毁后tr变成了一个悬空指针或者释放内存的指针。为什么tr 中的值只是一个单独的变量,恰好将地址保存到内存中的某个点?

【讨论】:

  • 地址的值没有变化。当然 tr 会显示相同的地址,但该地址中仍然有相同的 trial 对象。根据gdb,停在return 0行,就是这样。
  • Deallocation 并不意味着某处的内存被抹去,trial 类的对象仍然存在,但操作系统已将内存标记为空闲。如果你现在要创建一个new trial,可能malloc 会选择这个位置进行分配,内存的内容会发生变化。这就是为什么你总是必须初始化一个变量,因为简单地分配它会使变量在内存中保存数据。至于为什么 gdb 可以访问这个内存位置,这个位置,即使标记为空闲,仍然属于你的应用程序。
  • 我听到了。这实际上是很好的信息。我想我在删除public enable_shared_from_this&lt;trial&gt; 的继承后发现了我的困惑。一旦我这样做了,内存中仍然有试验对象,但整数指针无效。这就是我所期待的反应。因为删除一个整数指针,会使值 0,回到默认值。现在我删除了指向 Trial 对象的内存点,它可能以未定义的方式将内存恢复到默认 Trial 对象状态。
【解决方案2】:

如果您尝试以下调试代码,很明显shared_ptr sp1 在std::vector::clear() 调用后的引用计数为零。

trialVector.clear();
std::cout<<sp1.use_count();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多