堆栈销毁期间自动清理堆
Automatic heap cleanup during stack destruction
int* f()
{
int *p = new int[10];
return p;
}
int main()
{
int *p = f();
//using p;
return 0;
}
在堆栈销毁期间,当函数返回它的值时,某些编译器(当我被告知时暗示了 VS 或 gcc 等常见编译器(是否可以尝试自动释放本地指针(如本例中的 p(指向的内存?即使不是,我是否可以正常删除 main 中分配的内存?问题似乎是此时丢失了有关确切数组大小的信息。另外,在malloc和free的情况下,答案会改变吗?
谢谢。
只有局部变量被销毁释放。
在您的情况下,p
被"销毁"(释放(,但p
所指向的不是"销毁"(使用 delete[]
释放(。
是的,您可以,并且应该/必须在您的主上使用delete[]
。但这并不意味着在C++
中使用原始指针。您可能会发现这本电子书很有趣: 链接-阿尔夫-书
如果您想delete
函数"结束"(超出范围(时局部变量指向的内容,请使用std::auto_ptr()
(仅适用于非数组变量,不适用于需要delete[]
的变量(
另外,如果情况,答案会改变吗 的马洛克和自由?
不,但你应该确保你不要混合free()/new/delete/malloc()
.这同样适用于new/delete[]
和new[]/delete
。
不,它们不会free
或delete
你的指针指向什么。它们只会释放指针本身占用的几个字节。我认为,调用free
或delete
的编译器会违反语言标准。
只有当你有一个指向内存的指针,即来自f()
的结果,你才能main
delete[]
内存。您不需要跟踪分配的大小; new
和malloc
幕后为你做这件事。
如果要在函数返回时清理内存,请使用智能指针,例如 boost::scoped_ptr
或 boost::scoped_array
(均来自库的 Boost 集合(、std::auto_ptr
(在当前C++标准中,但即将被弃用(或std::unique_ptr
(在即将推出的标准中(。
在 C 语言中,不可能创建智能指针。
在堆栈销毁期间,当函数返回它的值时,某些编译器(当我被告知时暗示了 VS 或 gcc 等常见编译器(是否可以尝试自动释放本地指针(如本例中的 p(指向的内存?
简短回答:否
长答案:
如果您使用的是智能指针或容器(就像您应该的那样(,那么是的。
当智能指针超出范围时,内存将释放。
std::auto_ptr<int> f()
{
int *p = new int;
return p; // smart pointer credated here and returned.
// p should probably have been a smart pointer to start with
// But feeling lazy this morning.
}
std::vector<int> f1()
{
// If you want to allocate an array use a std::vector (or std::array from C++0x)
return std::vector<int>(10);
}
int main()
{
std::auto_ptr<int> p = f();
std::vector<int> p1 = f1();
//using p;
return 0; // p destroyed
}
即使不是,我是否可以正常删除 main 中分配的内存?
确保在不需要时立即正确释放所有内存是正常的。
请注意delete []
和delete
是不同的,因此在使用它们时要小心。
分配了new
的内存必须与 delete
一起释放。
分配了new []
的内存必须与 delete []
一起释放。
分配了malloc/calloc/realloc
的内存必须与 free
一起释放。
问题似乎是此时丢失了有关确切数组大小的信息。
记住此信息是运行时系统的问题。它的存储方式没有由标准指定,但通常它接近分配的对象。
另外,在malloc和free的情况下,答案会改变吗?
在C++你可能不应该使用malloc/free。但它们可以使用。使用它们时,应将它们一起使用,以确保内存不会泄漏。
您被误导了 - 局部变量被清理,但分配给局部指针的内存没有。如果不返回指针,则会立即出现内存泄漏。
不要担心编译器如何跟踪分配了多少元素,这是C++标准未解决的实现细节。只要知道它有效。(只要你使用delete[]
表示法,你做到了(
当您使用new[]
时,编译器会添加额外的簿记信息,以便它知道要delete[]
多少个元素。(以类似的方式,当您使用malloc
时,它知道要free
多少字节。一些编译器库提供扩展来找出该大小。
我还没有听说过编译器这样做,但编译器当然有可能检测(在许多情况下(从函数中分配的内存是否不再被指针引用,然后释放该内存。
但是,在您的情况下,内存不会丢失,因为您保留了一个指向它的指针,该指针是函数的返回值。
内存泄漏的一个非常常见的情况和此类功能的完美候选者是以下代码:
int *f()
{
int *p = new int[10];
// do something that doesn't pass p to external
// functions or assign p to global data
return p;
}
int main()
{
while (1) {
f();
}
return 0;
}
正如您所注意到的,指向已分配内存的指针丢失了,编译器可以绝对肯定地检测到这一点。
- 算法问题:查找从堆栈中弹出的所有序列
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- 为什么调用堆栈数组会导致内存泄漏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的 int main() 中出现堆栈溢出错误
- 堆栈和队列是否像C++中的数组一样传递?
- 拥有映射的现代方法,该映射可以指向或引用已在堆栈上分配的不同类型的数据
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 从堆栈分配的原始指针构造智能指针
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- 堆栈中大小变量输入错误 (C++)
- 堆栈问题(平衡表达式问题集)
- C++ 在堆栈中包含多态属性的类对象存储
- 用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
- 在 C++ 中使用链表进行堆栈
- 变量周围的堆栈'...'已损坏
- 在 gtest 中初始化堆栈上的引用变量的隔离错误
- C++线程的可用堆栈大小