在下面的程序中,我尝试释放std::map
对象的内存。
#include <map>
#include <iostream>
#include <unistd.h>
int main() {
// std::map<int, int> *mp = new std::map<int, int>;;
std::map<int, int> mp;
for(int i = 0; i < 999999; i++){
// mp->insert(std::pair<int, int>(i, 999999-i ));
mp[i] = 999999-i;
}
delete ∓
// delete mp;
pause();
}
该程序的两个版本(带注释或取消注释当前注释并注释相应的行)编译得很好,但当我尝试通过delete &mp
释放内存时(又名,mp是std :: map本身,而不是指向std :: map的指针,它告诉我这个奇怪的错误信息:
test14_1(47555,0x7fff75c6f300) malloc: *** error for object 0x7fff5c601918: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
有人知道为什么会这样吗?
答案 0 :(得分:4)
您的计划中有两个方面。
分配:: map
通过像你一样声明你的变量,你正在函数main()
的范围内创建一个::map
对象。地图在该函数的堆栈上分配,并在输入该函数(即函数scope { .. }
)时自动初始化。
释放:: map
因为在输入作用域时已在堆栈上分配了映射,所以在函数返回时会自动删除它(即函数作用域关闭)。你不必担心这个。
你做了什么......
通过调用delete
运算符,您尝试从进程堆中释放内存。 delete
运算符将指向已分配内存的指针作为参数,并通过编写&mp
来创建这样的指针。但是,因为mp
对象存在于您分配它的堆栈上,所以C ++运行时使用new
运算符为您提供了堆上pointer being freed was not allocated
的错误。
有趣的是,您已经在程序中拥有了正确的代码,您只是错误地配置了分配/免费:
// Allocate the memory on the heap, and free it.
// mp is a pointer to the allocated map.
int main() {
std::map<int, int> *mp = new std::map<int, int>;
// do stuff, e.g. mp->insert()
delete mp;
}
// Allocate the memory on the stack, freed automatically.
// mp is a reference to the allocated map.
int main() {
std::map<int, int> mp;
// do stuff, e.g. mp.insert()
// no need to free mp explicitly!
}
注意强>
您可能想了解C / C ++程序如何组织内存:堆和堆栈内存分配(看看here或here),以及指针和引用之间的区别内存分配(看看here或here)。
PS:你很幸运,错误信息。在禁用内存安全性的优化代码中(例如gcc&#39; s memory sanitizer),您的程序会表现得非确定并且可能会崩溃。
答案 1 :(得分:3)
您不需要删除std::map
,因为您没有使用new
运算符分配内存。像std::map
这样的所有标准容器都能够自己管理它们的内存。他们在内部使用allocator
进行内存管理。
答案 2 :(得分:1)
使用
std::map<int, int> mp;
delete ∓
类似于:
int i;
delete &i;
这是错误的。
只有在使用delete
分配对象时,才需要使用new
释放内存。
自动删除在堆栈上创建的对象。如果类的析构函数做了正确的事情,客户端代码就没有更多的事情可做了。在std::map
的情况下,析构函数将执行必要的释放。你的功能不需要做任何事情。
答案 3 :(得分:-1)
这是基本的RAII。
任何堆栈本地对象,包括int / float等类型的简单变量,或者就像容器一样,都会在范围的末尾销毁。
明确销毁,
{
vector<int> v1;
map<int,int> m1;
delete &m1;
} // implicit destruction of v1 and m1!
使用显式删除语句,生成的代码最终将释放已释放的内存。