2014-08-29 89 views
0

我想知道有多大的物体对于堆栈来说太大了?如果我们正在谈论普通PC(无论是Windows还是某些Linux)。我试图找到答案,但如果对象太大,我发现所有的东西都是在堆上分配的。但是什么太大?几KB?或几百KB?我知道这通常不是问题,但由于我不知道答案,所以它困扰着我。堆栈应该如何使用大对象堆栈?

一些代码:

int main() 
{ 
    int a[1000][300]; /* enough for stack overflow :) on Visual Studio 2012 without any specific setting. int a[1000][250] is Ok */ 
    return 0; 
} 

一些更多:

int main() 
{ 
    MySmallClass a; // I want to use RAII 
    MyBigClass b; // ouch I shouldn't do it 
    unique_ptr<MyBigClass> c(new MyBigClass()) // So I would do something like this to keep RAII 
    return 0; 
} 

由于Visual Studio中似乎有问题,堆栈分配一样大,只有1MB它似乎是合理的分配堆栈对象上由于堆栈可能会相当深,因此最大大小为几KB。它并不多,并且我甚至不知道(因为我不想知道)第三方对象有多大,我只能期望它们会合理的小。

我在做大静态数组测试一些性能时,实际上只遇到过这种问题。所以在现实生活中它可能不是常见的问题,但仍然...

+1

它不是Visual Studio - 它是Windows,为您提供1MB的默认堆栈大小。如果你控制线程创建,你可以要求更多。 – Gabe 2014-08-29 17:27:12

+0

'这不算什么,我甚至不知道第三方对象(因为我根本不想知道)他们有多大'任何第三方库都会给你提供可以很容易地把堆栈炸掉的对象。 IMO低质量图书馆。 – PaulMcKenzie 2014-08-29 17:33:57

+1

这为什么如此重要?只要选择一个任意的限制,然后回去做有用的工作。如果你不能挑选自己,那么*完美*限制显然是65536字节。 – fredoverflow 2014-08-29 17:41:35

回答

0

这个问题没有简单的答案。

单个对象? 一些运行时间确定的数量?
每个循环或递归调用都创建了对象吗?

因为堆栈溢出可能难以识别,所有这些选择都会影响您在选择将大对象放入堆栈时的谨慎程度。


在我工作过的嵌入式系统中,stack vs heap很少被讨论。相反,问题仅仅是“对象的生命周期是多少”。

而且,也许令人惊讶的是,大多数“重要”的对象都是在创建时创建的,并且从未遭到破坏。即它们一直持续到系统重置或断电。

在那个嵌入式环境中,重要的对象在堆中。


当然,在一个实质的系统中,也有很多对象只能持续到函数(或方法)的末尾。

这些短期对象可能适合(或不适用)与使用它们的单线程关联的堆栈。在该版本的vxWorks中没有运行时堆栈大小更改机制(我知道)。每个任务(我认为对应于linux线程)都有一个在编译时确定的堆栈大小。有时,我们确实会溢出堆栈。

当你发现并说服自己,你已经在你的程序堆栈溢出,有2个解决方案(或者更多)

  • 在一个特定的情况下,我的团队的决定是扩大特定线程堆栈大小。溢出对该线程是唯一的。

  • 在其他几个中,我们在函数的开始处将对象添加到堆中,并在退出时将其删除。很简单,对吧?

这是唯一的两个选择吗?也许。

所以,如果你必须有一个数字,我会说找别人的经验法则。


随着嵌入式系统的开发者熟练,我会形容我的选择,如:

  • 我一直不平凡的对象在堆上。

  • 小批量堆叠上的任何相对简单的物体。

  • 终身的问题只能从堆栈推的东西堆

  • 更大的尺寸只能从堆栈推的东西堆

就个人而言,我非常喜欢使用新删除并对所有权问题发表意见。然而......我的'风格'选择并不是每一个人的选择。并且有暗示,最终的复杂性会混淆什么任务都拥有什么对象的任何知识(因此该任务应该删除的对象)

现在,找出非繁琐意味着大量的文献,而且很简单。


对于标准::向量,和std ::字符串,性病:: stringstream的,而地图的,还有这些都是比较复杂的对象(恕我直言)

但是,如果您使用sizeof(),即使在填充时它们也小得惊人地小。我认为这意味着这些都是堆访问的“前端”。另一方面,它们表现良好,也许还在做其他事情(与堆不相关),但我没有研究过它。

更多要学习。