c++ - 唯一指针 : pointer being freed was not allocated when emplaced in list

标签 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:对象 0x7ffee81489ac 的 *** 错误:未分配正在释放的指针 *** 在malloc_error_break 设置断点调试 [1] 59842 中止./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 会导致其销毁失败?

最佳答案

未定义的行为可能导致任何结果,从崩溃到表面上成功的运行,再到英国投票退出欧盟(哎呀,对不起,伙计们……空指针解引用的作用真是太神奇了)。

编译器是极其复杂的东西。您的程序不是将由目标计算机按顺序执行的指令的一对一映射;它是对您希望计算机如何运行的粗略描述。两者之间的转换非常深奥和复杂。当你偏离轨道时,你会以这样一种方式破坏语言,即编译器的内部工作方式——不断做出假设并采取它知道允许这样做的捷径,尤其是在应用所谓的“优化”时——被打破不可预知的方式。

这是其中之一。

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

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

只是不要用你没有动态分配的东西做智能指针(或者,如果你出于某种原因真的想要,提供一个不会尝试删除东西的自定义删除器那不是新的d)。很简单!

关于c++ - 唯一指针 : pointer being freed was not allocated when emplaced in list,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51637247/

相关文章:

Android NDK - 如何类型转换对象类

c++ - 从属名称解析和命名空间标准/标准库

c++ - 声明现有原始指针所有权的正确方法

c++ - xcode 7 如何抑制警告 "overrides a member function but is not marked ' override'”

c++11 - unique_ptr<Derived> 到 unique_ptr<Base> 是否自动向上转换?

c++ - 返回 NULL 值

c++ - 如何查找 C/C++ 中线程使用的总时间?

c++ - C++中指向字符数组的指针

C++ 无法返回 sf::Texture

c++ - 将 crtp 与公共(public)接口(interface)类一起使用时,如何避免虚拟调用开销?