最近我在c中创建了一个程序,其唯一目的是使用递归方法溢出堆栈。 显然没有可移植的方式(比如try / catch块,至少在c中),以避免下一次调用函数导致堆栈溢出。 我的问题是,在您看来,高级语言应该提供调整堆栈大小的替代方案,可能是编译器上的标志,或者这些应用程序必须使用低级语言构建。
答案 0 :(得分:2)
通常我认为调整计算机或操作系统的限制可能不是一个好主意。如果你发现自己堆满了内存,内存耗尽,打开文件句柄耗尽等等,重新设计你的程序是明智的,而不是想知道如何避免这些限制。
答案 1 :(得分:2)
通常,这是加载器的工作(加载EXE的东西,修复对共享库的引用,重新定位代码等)来设置内存区域,但它通常是响应头文件可执行文件中的字段链接器放在那里。
但是这种事情并没有被任何标准所涵盖,它是操作系统级的事情。
答案 2 :(得分:1)
堆栈的大小通常由用于创建应用程序的构建工具设置,例如编译器和链接器。执行此操作的方法始终是特定于平台的,因此无法通过标准化的高级语言或标准化的低级语言执行此操作。
答案 3 :(得分:1)
显然没有可移植的方式(比如try / catch块,至少在c中),以避免下一次调用函数导致堆栈溢出。
这是为了支持无法动态扩展堆栈的平台,并且在每次调用时都不会在运行时检查堆栈是否仍处于边界内。任何类型的检查(除非由硬件完成)都会减慢绝大多数代码的速度,这些代码永远不会出现在堆栈末尾附近,因此实际上并不符合C或C ++的精神。
因此,递归太深是硬件异常(或内存损坏)。 C和C ++不会尝试指定硬件异常上发生的事情:它们超出了语言范围和未定义的行为,因此没有可移植的恢复方式。
相比之下,当你递归太深时,Java会抛出StackOverflowError。虽然不推荐,但可以抓住这个。
我还没有看到过带有isThereEnoughStackFor原语的语言,可以让你写一下:
if (isThereEnoughStackFor(foo)) {
foo(12);
} else {
printf("error - no stack\n"); // I hope there's enough stack for printf
}
要使任何此类方案有效,您需要知道堆栈foo需要多少。这取决于foo,但也可能取决于所有foo调用,因此也取决于它的参数。所以foo及其所有依赖项要么需要报告它们需要多少堆栈(在这种情况下你怎么知道有足够的堆栈来计算它?),或者在调用任何东西之前需要进行类似的检查(在这种情况下你需要) d有一个有限的功能菜单,你被“允许”调用,就像信号处理程序一样。
一旦你有了运行时多态性(在C中,考虑foo是一个函数指针而不是一个函数名),在每次调用时通过内置测试以外的任何方式检查堆栈已被证明是不可能或不值得努力。