Unique_ptr:在列表中放置时未分配释放的指针
Unique_ptr: pointer being freed was not allocated when emplaced in list
我有一个简单的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
会导致其销毁失败?
未定义的行为可能会导致任何事情,从崩溃到明显成功的竞选,再到英国投票退出欧盟(哇,对不起,伙计们…空指针取消引用的作用真是太神奇了(。
编译器是极其复杂的东西。您的程序不是目标计算机将按顺序执行的指令的一对一映射;它大致描述了您希望计算机的行为。两者之间的转换是高度深奥和复杂的。当你偏离轨道时,你会破坏语言,使编译器的内部工作方式—他们不断做出假设,走自己知道可以走的捷径,尤其是在应用所谓的"优化"时;以不可预测的方式破碎。
这是其中之一。
简而言之,如果期望UB做任何特别的事情,那么您已经失败了。
通过分析编译器的源代码和生成的程序集,可以准确地确定UB在这种情况下的行为原因。但这将是一个漫长、艰巨且最终毫无意义的过程。
只是不要用你没有动态分配的东西来制作智能指针(或者,如果你出于某种原因真的想,提供一个自定义的deleter,它不会尝试delete
,而不是new
d(。易于理解的
我认为第二个例子中的变量p
只是经过了优化,因此没有导致运行时错误。
但发生的错误是显而易见的,它试图释放在堆栈上分配的内存。请注意,智能指针通常与堆分配内存一起使用,而不是与堆栈上分配的内存一起使用。
我已经复制并编译了您的代码:
$ g++ omg.cpp && ./a.exe
Aborted (core dumped)
您可以尝试添加另一个间接级别:
int main(void) {
int x = 5;
{
std::unique_ptr<int> p(&x);
}
}
看看它是否有帮助。
- 正在理解智能指针,但出现错误:未分配正在释放的指针
- 调用析构函数以释放动态分配的内存
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- 错误:malloc:对象 0x7f9edf504080 的 *** 错误:未分配正在释放的指针
- 给定一个指向堆分配内存的指针,智能指针实现如何为其找到合适的释放函数?
- 是否可以使用分配器对象来释放另一个分配器分配的内存?
- 释放动态分配的内存时是否需要执行此额外步骤
- 整数内存分配/释放
- 我是否需要在 c++ 中从本地指针中释放分配的内存?
- 未分配释放C++(C 字符串)指针
- 未分配被释放的指针(将堆栈实现为链表时)
- 在不释放所有动态分配的资源的情况下结束程序是否有风险
- Unique_ptr:在列表中放置时未分配释放的指针
- C++内存分配/释放和自由空间错误
- 带有QT的C 应用中的IIMEBRA代码给出malloc:***对象XXXXXX的错误:未分配释放的指针
- 删除引用时出现未分配释放的指针错误
- 指针的内存分配/释放
- 内存分配/释放错误(非常小的代码)
- c++堆内存分配/释放
- 内存管理——用于分配/释放I/O缓冲区的现代c++风格