捕获堆栈溢出 [英] Catching stack overflow

查看:168
本文介绍了捕获堆栈溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是赶在C堆栈溢出的最佳方式?

What's the best way to catch stack overflow in C?

更具体地说:

一个C程序包含了脚本语言的跨preTER。

A C program contains an interpreter for a scripting language.

脚本不信任,可能包含无限递归的错误。间preTER必须能够捕获这些和顺利继续。 (显然,这可以部分地通过使用软件栈处理,但是如果库code的实质性块可以用C写的性能大大提高;在最低限度,这需要C函数运行在由脚本创建递归数据结构。 )

Scripts are not trusted, and may contain infinite recursion bugs. The interpreter has to be able to catch these and smoothly continue. (Obviously this can partly be handled by using a software stack, but performance is greatly improved if substantial chunks of library code can be written in C; at a minimum, this entails C functions running over recursive data structures created by scripts.)

捕捉堆栈溢出将涉及的longjmp返回到主回路的preferred形式。 (这是完全没关系丢弃在主循环低于栈帧持有的所有数据。)

The preferred form of catching a stack overflow would involve longjmp back to the main loop. (It's perfectly okay to discard all data that was held in stack frames below the main loop.)

回退便携式解决方案是采用局部变量的地址来监视当前堆栈深度,并为每一个递归函数包含到使用此方法的堆栈检查函数的调用。当然,这会带来在正常情况下,一些运行时开销;如果我忘了把堆栈检查呼叫在一个地方同时也意味着,国米preTER将有一个潜在的bug。

The fallback portable solution is to use addresses of local variables to monitor the current stack depth, and for every recursive function to contain a call to a stack checking function that uses this method. Of course, this incurs some runtime overhead in the normal case; it also means if I forget to put the stack check call in one place, the interpreter will have a latent bug.

是否有这样做的更好的办法?具体来说,我不期待一个更好的便携式解决方案,但如果我对Linux的系统具体的解决方案,另外一个用于Windows,那会好起来的。

Is there a better way of doing it? Specifically, I'm not expecting a better portable solution, but if I had a system specific solution for Linux and another one for Windows, that would be okay.

我已经看到了一些所谓的结构化异常处理的Windows引用,但我见过的引用是大约翻译成C ++异常处理机制,这一点;能不能从C访问,如果是的话是不是对于这种情况有用吗?

I've seen references to something called structured exception handling on Windows, though the references I've seen have been about translating this into the C++ exception handling mechanism; can it be accessed from C, and if so is it useful for this scenario?

据我了解Linux的让你赶上一个分割故障信号;是它能够可靠地变成一个longjmp的回你的主循环?

I understand Linux lets you catch a segmentation fault signal; is it possible to reliably turn this into a longjmp back to your main loop?

Java的似乎支持在所有平台上捕捉堆栈溢出的例外;它是如何实现的?

Java seems to support catching stack overflow exceptions on all platforms; how does it implement this?

推荐答案

关闭我的头顶,一路追赶过度堆栈增长是检查堆栈帧的地址相对差:

Off the top of my head, one way to catch excessive stack growth is to check the relative difference in addresses of stack frames:

#define MAX_ROOM    (64*1024*1024UL)    // 64 MB

static char *   first_stack = NULL;

void foo(...args...)
{
    char    stack;

    // Compare addresses of stack frames
    if (first_stack == NULL)
        first_stack = &stack;
    if (first_stack > &stack  &&  first_stack - &stack > MAX_ROOM  ||
        &stack > first_stack  &&  &stack - first_stack > MAX_ROOM)
        printf("Stack is larger than %lu\n", (unsigned long)MAX_ROOM);

    ...code that recursively calls foo()...
}

这第一栈帧的地址富()比较当前堆栈帧地址,如果差值超过 MAX_ROOM 写入消息。

This compares the address of the first stack frame for foo() to the current stack frame address, and if the difference exceeds MAX_ROOM it writes a message.

这假设你在使用一个线性的架构始终保持增长下降或始终成长向上堆栈,当然。

This assumes that you're on an architecture that uses a linear always-grows-down or always-grows-up stack, of course.

您不必做此项检查在每一个功能,但往往不够,你打你所选择的限制之前过大的堆栈增长被抓住。

You don't have to do this check in every function, but often enough that excessively large stack growth is caught before you hit the limit you've chosen.

这篇关于捕获堆栈溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆