Unique_ptr:放置在列表中时未分配要释放的指针

时间:2018-08-01 15:34:02

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

我有一个像这样的简单C ++程序:

#include <iostream>
#include <list>
#include <memory>

int main(void) {
  std::list<std::unique_ptr<int>> l;
  int x = 5;
  // throws runtime error: pointer being freed was not allocated
  l.emplace_back(&x);
}

程序运行时,我将获得以下输出:

a.out(59842,0x7fffb13d1380) malloc: *** error for object 0x7ffee81489ac: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug [1] 59842 abort ./a.out

这告诉我,在销毁列表期间,已创建的unique_ptr对象将被销毁,并且在销毁期间,从未x释放指向malloc的指针。

但是我希望在unique_ptr超出范围且为destroyed的情况下也会发生同样的情况:

#include <iostream>
#include <list>
#include <memory>

int main(void) {
  int x = 5;

  // does not throw runtime error when falling out of scope and being destructed
  std::unique_ptr<int> p(&x);
}

但是,当以上unique_ptr p超出范围并被破坏时,程序可以正常运行。为什么第一个程序在销毁unique_ptr时给我一个错误,而第二个却没有?为什么在列表中加上unique_ptr会导致其销毁失败?

3 个答案:

答案 0 :(得分:3)

未定义的行为可能导致任何事情,从崩溃到表面上看似成功的运行,再到英国投票退出欧盟(哎呀,对此感到抱歉,伙计们……空指针取消引用可以做什么令人惊讶)。

编译器是极其复杂的东西。您的程序不是目标计算机将按顺序执行的指令的一对一映射。它大致描述了您希望计算机如何运行。两者之间的转换是深奥而复杂的。当您进行滑雪训练时,您会以一种破坏编译器内部工作的方式来破坏语言,编译器的内部工作会不断地做出假设,并采取允许其执行的捷径,特别是在应用所谓的“优化”时尤其如此。不可预测的方式。

这是其中之一。

简而言之,如果您期望UB做一些特别的事情,那么您已经失败了。

通过分析编译器的源代码和从构建中产生的程序集,有可能确切确定UB在这种情况下的行为表现。但这将是一个漫长,艰巨且最终完全没有意义的过程。

请不要从没有动态分配的内容中创建智能指针(或者,如果出于某些原因,确实要提供自定义的删除器,而该删除器将不会尝试delete那些不是' t new d)。简单!

答案 1 :(得分:1)

我认为发生的事情是第二个示例中的变量p刚刚被优化,因此不会导致运行时错误。

但是发生的错误很明显,它试图释放在堆栈上分配的内存。请注意,智能指针通常与堆分配的内存结合使用,而不是与在堆栈上分配的内存结合使用。

答案 2 :(得分:-3)

我已经复制了您的代码并对其进行了编译:

$ g++ omg.cpp && ./a.exe
Aborted (core dumped)

您可以尝试添加另一个间接级别:

int main(void) {
    int x = 5;
    {
        std::unique_ptr<int> p(&x);
    }
}

看看是否有帮助。