oma*_*mar 10 c++ recursion exception-handling exception
是否有可能stack overflow exception
在递归C++函数中捕获?如果是这样,怎么样?
那么在这种情况下会发生什么
void doWork()
{
try() {
doWork();
}
catch( ... ) {
doWork();
}
}
Run Code Online (Sandbox Code Playgroud)
我不是在寻找特定操作系统的答案.总的来说
Cha*_*via 11
实际上没有可移植的方法.失控的递归函数在尝试将堆栈帧分配到堆栈地址空间之外时,通常会导致无效的内存访问.这通常会使程序崩溃,因为操作系统会出现分段错误/访问冲突.换句话说,它不会抛出可以通过语言以标准方式处理的c ++异常.
Jer*_*ner 11
它本身并不例外,但如果您只想将堆栈使用量限制为固定数量,则可以执行以下操作:
#include <stdio.h>
// These will be set at the top of main()
static char * _topOfStack;
static int _maxAllowedStackUsage;
int GetCurrentStackSize()
{
char localVar;
int curStackSize = (&localVar)-_topOfStack;
if (curStackSize < 0) curStackSize = -curStackSize; // in case the stack is growing down
return curStackSize;
}
void MyRecursiveFunction()
{
int curStackSize = GetCurrentStackSize();
printf("MyRecursiveFunction: curStackSize=%i\n", curStackSize);
if (curStackSize < _maxAllowedStackUsage) MyRecursiveFunction();
else
{
printf(" Can't recurse any more, the stack is too big!\n");
}
}
int main(int, char **)
{
char topOfStack;
_topOfStack = &topOfStack;
_maxAllowedStackUsage = 4096; // or whatever amount you feel comfortable allowing
MyRecursiveFunction();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
没有便携的方式.但是,有一些非便携式解决方案.
首先,正如其他人所说,Windows提供了一个非标准__try
和__except
框架所谓结构化Exeption处理(您的具体答案是知识库).
其次,alloca
- 如果实现正确 - 可以告诉你堆栈是否即将溢出:
bool probe_stack(size_t needed_stack_frame_size)
{
return NULL != alloca(needed_stack_frame_size);
};
Run Code Online (Sandbox Code Playgroud)
我喜欢这种方法,因为在最后probe_stack
,alloca
分配的内存被释放并可供您使用.不幸的是,只有少数操作系统alloca
正确实现. alloca
永远不会NULL
在大多数操作系统上返回,让你发现堆栈已经溢出一个壮观的崩溃.
第三,类UNIX系统通常有一个标题,调用ucontext.h
函数来设置堆栈的大小(实际上,将多个堆栈链接在一起).您可以跟踪堆栈中的位置,并确定是否即将溢出.Windows具有类似的能力a la CreateFiber
.
从Windows 8开始,Windows具有专门针对此的功能(GetCurrentThreadStackLimits)
大多数现代操作系统总是这样做。如果您想自己执行此操作,则必须知道堆栈的最大“安全”地址(或者同样进行一些数学计算以确定可以安全调用该函数的次数),但这可能会变得非常棘手如果您不自己管理调用堆栈,因为操作系统通常(出于充分的理由)向您隐藏这一点。
如果您在内核空间中编程,这会变得更加容易,但我仍然质疑您为什么这样做。如果出现堆栈溢出,可能是因为算法决策错误或代码中存在错误。
编辑:刚刚意识到您想要“捕获所产生的异常”。我认为我的答案根本不直接回答这个问题(这个例外是否存在?我会认为这是一个巨大的失败),但我将把它留给洞察力。如果您希望将其删除,请在评论中告诉我,我会这样做。