用C / C ++编程时;作为一个经验法则,什么是切断点,而不是char array[MAX_PATH+1]={0}
人将使用:
char *array=nullptr;
array=new char [MAX_PATH+1];
...code...
delete [] array;
人们在什么时候采取行动来保留堆叠上的空间?
20年前,我被告知你应该在堆上分配超过32个字节的所有数组,无论性能成本如何,并为简单变量保存堆栈。我已经看到很多现代示例代码非常使用堆栈,所以这种想法改变了吗?
答案 0 :(得分:8)
堆栈分配的好处是您不必检查失败,您不必担心内存碎片,并且在函数返回时自动释放内存。缺点是您无法检查是否成功,并且通常在失败时会发生不良事件。
没有虚拟内存(例如,在小型微控制器上),通常可用的内存较少。如果你的程序在堆栈上分配了太多的空间,它只会溢出堆栈并写入超出为堆栈保留的空间之外的任何内容。您可以留出更多的堆栈空间来处理最坏的情况,但无论您是否需要,该空间始终专用于堆栈。而使用动态分配时,您只需在使用它时付费,并且可以检查malloc
的返回代码以确定是否发生了故障(或者在new
上捕获异常,以便人们尝试挤压C ++进入微控制器)。或者,您可以静态地为对象保留一部分RAM,如果应用程序总是需要它,因为这样它具有更可预测的运行时行为,您不必担心碎片。
使用虚拟内存,操作系统可以通过在堆栈末尾向连续的虚拟地址添加页面来动态扩展堆栈。这样,您只需为您正在使用的金额堆栈支付物理内存。但是,如果你有一个很小的(32位或更少?)地址空间,如果你有很多线程和太多的堆栈分配,你仍然会遇到麻烦。
每个线程必须为其堆栈提供连续的空间,并且必须与系统中的其他所有内容共享。例如,如果操作系统占用1 GB的地址空间(并非罕见),并且您希望1 GB用于线程堆栈,则会为堆,数据和代码留下2 GB的空间。如果你有16个线程,这意味着每个线程堆栈可以有大约64 MB。根据您的应用程序,可能会或可能不会。
如果您有更多线程或更大的堆栈分配对象,则必须调整线程堆栈大小和堆大小以获得正确的平衡。如果你错了,你的程序分段会在堆栈溢出时出错。因此,建议在堆上进行所有“大”分配,因为更可预测的运行时行为。
20年前,一个4 GB的地址空间很多的空间用于堆,数据,代码和堆栈 - 今天不是那么多。幸运的是,地址空间也变得更大了。使用64位地址空间,在耗尽物理内存之前,您将耗尽DRAM,即使您有超过1 TB的DRAM。
几点警告
运行时经常对堆栈大小捕获失控递归错误施加任意限制。如果你使用的堆栈比运行时系统预期的多得多,你可能需要告诉它给你一个更大的堆栈。通常,默认大小足够大,通常不难改变。
操作系统/运行时不像回收堆栈空间那样好。由于您的程序需要更多的堆栈空间,因此它将获得新页面。在线程退出之前很可能不会释放这些页面(至少在那种情况下是这样)。如果您正在使用堆栈空间,那不是什么大问题。如果它很少使用并且线程运行很长时间,如果你有后备存储器,内存将被交换到磁盘(对于带有旋转驱动器的台式机/笔记本电脑通常不是问题,但对于iOS8或Android 64可能不太好)位)。
如果您希望您的代码在具有较大物理和虚拟内存空间的系统上运行,而您计划堆栈分配的对象,则堆栈分配可能正常。在大多数情况下,收益将超过成本。
答案 1 :(得分:4)
您的问题的答案取决于您的系统。您只需要关注递归编程中的堆栈分配。
在现代系统上,您可以轻松完成:
char array [123456];
但你不会在通过递归重复调用自身的函数中这样做。
答案 2 :(得分:4)
链接器设置堆栈大小。任何静态分配在Windows上最多可处理1 GB(在其他系统上可能不同)。但是,Windows上的默认堆栈大小为1MB(Linux上为8MB)。因此,动态分配的主要好处是您不必事先知道大小,或者您的程序需要一些非常大的分配。