当您使用允许对非常大的对象使用自动分配的语言进行编程时,您何时以及如何担心堆栈大小?关于堆栈大小的推理是否有任何经验法则?
答案 0 :(得分:13)
当您使用允许您对非常大的对象使用自动分配的语言进行编程时......
如果我想分配一个非常大的对象,那么我可能会在堆上分配一个非常大的对象而不是堆栈,而是包含在auto_ptr
中(在这种情况下,当它超出范围时,它将被释放,就像堆栈驻留对象一样,但不必担心堆栈大小。)
...您何时以及如何担心堆栈大小?
我保守地使用堆栈的习惯(例如,在堆上分配大于512字节的任何对象),我知道堆栈有多大(例如默认大约一兆字节),因此知道我不用担心。
关于堆栈大小的推理是否有任何经验法则?
答案 1 :(得分:11)
你在微控制器上关心它,你经常必须明确地指定堆栈空间(或者在RAM用于静态分配+任何RAM程序空间之后你得到剩余的东西)。
答案 2 :(得分:7)
时,您开始担心堆栈大小
答案 3 :(得分:6)
如果您正在编写一个小小的嵌入式平台,那么您一直担心它,但您也确切地知道它有多大,并且可能有一些有用的工具可用于查找堆栈的高水位标记
如果你不是,那么在程序崩溃之前不要担心:) 除非你要分配严重的大对象(数十KB),否则它永远不会成为问题。
但是,请注意,根据定义,堆栈上的对象是临时的。经常构造(并且可能破坏)大对象可能会导致性能问题 - 所以如果你有一个大对象,它可能应该是持久的而且是基于堆的,而不是堆栈大小。
答案 4 :(得分:4)
我从不担心。如果堆栈溢出,我很快就会知道它。此外,在C ++中,实际上很难在堆栈上创建非常大的对象。关于这样做的唯一方法是:
struct S {
char big[1000000];
};
但是使用std :: string或std :: vector会使问题消失。
答案 5 :(得分:3)
你不应该首先避免使用堆栈来分配大型对象吗?使用堆,没有?
答案 6 :(得分:3)
我的经历: 当你使用递归函数时,请注意堆栈大小!!
答案 7 :(得分:3)
您何时担心堆栈大小?
从不。
如果你有堆栈大小问题,这意味着你做了别的错误,应该修复它,而不是担心堆栈大小。
对于实例:
答案 8 :(得分:2)
当调用堆栈非常深并且每个函数分配变量(在堆栈上)时,我担心嵌入式系统上的堆栈大小。通常,当系统因堆栈中的变量发生变化而意外崩溃(堆栈溢出)时,会发生恐慌。
答案 9 :(得分:2)
您通常无法在堆栈上拥有大型对象。它们几乎总是在内部使用堆,因此即使它们在堆栈中,它们的数据成员也不是。即使是具有大量数据成员的对象,堆栈上通常也会有64个字节以下,其余的都在堆上。如果你有很多线程和大量的递归,那么堆栈通常只会成为一个问题。
答案 10 :(得分:2)
在Symbian上玩了很多这个游戏:什么时候使用TBuf(堆栈上有存储的字符串),什么时候使用HBufC(它在堆上分配字符串存储,比如std :: string,所以你必须应对离开,你的功能需要一种失败的方法。)
当时(可能还是,我不确定),Symbian线程默认有4k的堆栈。要操作文件名,您需要指望最多使用512个字节(256个字符)。
你可以想象,收到的智慧“永远不会把文件名放在堆栈上”。但事实上,事实证明,你可以比你想象的更频繁地逃避它。当我们开始运行真正的程序(TM),比如游戏时,我们发现我们需要的方式比默认的堆栈大小更多,并且它不是由于文件名或其他特定的大型对象,而是由于其复杂性游戏代码。
如果使用堆栈会使您的代码更简单,并且只要您正确测试,并且只要您没有完全超越(没有多层次的文件处理函数 all < / em>在文件夹上放一个文件名),然后我会说尝试一下。特别是如果函数需要能够失败,无论你是使用堆栈还是堆。如果出错,您可以将堆栈大小加倍并在将来更加小心,或者为您的函数添加另一个失败案例。也不是世界末日。
答案 11 :(得分:2)
只有时间才是线程并且必须自己定义,当你进行递归时或者由于某种原因你正在分配给堆栈时。否则,编译器会确保您有足够的堆栈空间。
默认情况下,CreateThread仅为堆栈分配0x100000个字节。
答案 12 :(得分:1)
在决定是否在堆栈上分配对象与堆时,还需要考虑性能问题。堆栈上的内存分配非常快 - 它只涉及移动堆栈指针,而使用new / delete或malloc / free的动态分配/释放相当昂贵,尤其是在每个线程没有堆的多线程代码中。如果你有一个在紧密循环中调用的函数,你可能会错误地将更大的对象放在堆栈上,同时记住其他答案中提到的所有多线程警告,即使这意味着必须增加堆栈空间,大多数连接器都允许你这样做。
答案 13 :(得分:1)
一般来说,堆栈上的大量分配是不好的,原因有几个,其中最重要的原因是它们可能导致问题长时间保持隐藏状态。
问题在于检测堆栈溢出并不容易,大量分配可能会破坏大多数常用方法。
如果处理器没有内存管理或内存保护单元,则必须特别小心。但是使用某种MMU或MPU的事件,硬件可能无法检测到堆栈溢出。一个常见的方案是,如果大堆栈对象大于页面,则保留堆栈下方的页面以捕获溢出。可能只是堆叠的另一个线程坐在那里哎呀!你刚刚创造了一个非常讨厌,很难找到的bug。
无限递归通常很容易捕获,因为堆栈增长通常很小,会触发硬件保护。
答案 14 :(得分:1)
我没有。在编写正常的编程时,担心这些事情要么是过早的悲观化,要么是过早的优化。无论如何,要在现代计算机上搞砸是非常困难的。
我曾经写过一个CSV解析器,在玩弄时试图获得最佳性能,我在堆栈上分配数千个1K缓冲区。性能非常出色,但RAM从正常的30MB内存增加到大约1GB。这是由于CSV文件中的每个单元都有一个固定大小的1K缓冲区。
就像所有人都说的那样,除非你在做递归,否则你不必担心它。
答案 15 :(得分:1)
(是的,这些都是现实生活中的混乱。)
答案 16 :(得分:0)
当您编写一个回调时,您会担心它,该回调将由您无法控制的运行时(例如,MS RPC运行时)生成的线程调用,其堆栈大小由该运行时决定。不知怎的like this。
答案 17 :(得分:0)
在以下情况下,我遇到了堆栈空间不足的问题:
提供我:
我通常没有任何问题,所以很遗憾不知道应该有什么好的默认值。
答案 18 :(得分:0)
在以下情况下开始担心堆栈大小:
可修改输入参数的示例:
in my_func(size_t input_param)
{
char buffer[input_param];
// or any other initialization of a big object on the stack
....
}
建议: