我知道通过使用operator new()我可以耗尽内存并且我知道如何保护自己免受这种情况的影响,但是我可以通过在堆栈上创建对象来耗尽内存吗?如果是,我如何检查对象创建是否成功? 谢谢。
答案 0 :(得分:4)
你可以耗尽一堆。在这种情况下,您的程序可能会立即崩溃并出现堆栈溢出异常。
堆栈的大小也是如此,因此您可以将其视为一块内存。例如,函数内部的变量在此处分配。此外,当您调用函数时,调用本身也存储在堆栈中(非常简化,我知道)。因此,如果您进行无限递归(如另一个答案中所述),则堆栈会被填充但不会被清空(当函数返回时会发生这种情况,有关调用的信息被“删除”)所以在某些时候您将填满整个空间分配给您的程序堆栈,您的应用程序将崩溃。
请注意,有多种方法可以确定/更改堆栈的大小。
答案 1 :(得分:4)
只要看看这个网站的标题,你就会看到答案。 如果你想看到“现场”会发生什么,写下一些无限递归。
即
void fun() { fun(); }
答案 2 :(得分:3)
是的,你可以耗尽筹码。在常见系统上,硬件/操作系统会捕获并中止您的程序。但是,很难这样做。您必须在堆栈上创建大对象(自动数组)或进行深度递归。
请注意,如果您使用常见的抽象,例如std::string
,std::vector
等,您几乎不会耗尽堆栈,因为当它们存在于堆栈中时,它们的数据在堆上。 (对于除std::tr1::array
之外的std lib附带的所有STL容器都是如此。)
答案 3 :(得分:1)
是的,请参阅网站的名称。你无法真正检查对象创建是否成功 - 程序只是在堆栈溢出时崩溃。
答案 4 :(得分:1)
内存不是无限的,所以无论你在哪里分配对象,你最终都会用完它。
答案 5 :(得分:1)
好的,但是当'对象创建'成功时,你需要发现尖锐的反应。
class MyObject {
private:
int x
public:
MyObject() { x = 0; }
};
int main(int argc, char **argv) {
IWantToExhaustTheStack();
return 0;
}
void IWantToExhaustTheStack() {
MyObject o;
IWantToExhaustTheStack();
}
现在编译并运行它,很快你的对象创建就可以了。当程序失败时,您将知道对象创建失败。
开玩笑说,并且为了回应您更新的问题,没有标准的方法来确定堆栈大小。请参阅:与Win32相关的此Stackoverflow Question。但是,堆栈用于调用方法并保存本地临时和返回变量。如果要在堆栈上分配大对象,那么你真的应该考虑将它们放在堆上。
答案 6 :(得分:0)
是的,您可以耗尽堆栈而无法测试对象创建是否失败,因为失败后这已经太晚了。
通常,防止堆栈溢出的唯一方法是以不超过给定限制的方式设计应用程序。即如果递归修改图像然后限制图像大小或使用其他算法来处理大图像。
观看递归(不太深),观看alloca(不要太多)。在检查堆栈使用情况时观察窥视。
在OpenSolaris中,几乎没有可以控制堆栈的函数。