在C90中实现一个无溢出的系统堆栈

huangapple go评论126阅读模式
英文:

Implementing an overflow-free system stack in C90

问题

我刚刚读到了关于Google Go如何默认使用减小的堆栈大小来创建每个线程,并在溢出时链接到新的堆栈(请参见这里的第16页)。我想知道在C语言中实现这一点的最佳方法。

我必须说我不是C语言专家,所以可能有更好的方法来检测C语言中的堆栈溢出,但鉴于我的无知,我想我会这样实现:

我首先想到的是,每当我们有一个全新的堆栈时,我们获取一个堆栈变量的地址,并且大致获得了起始堆栈地址。然后,我们需要能够获取线程的堆栈空间大小。如果线程不是主线程,这是可能的,但我不知道如何在C语言中获取这些信息。

然后,我们需要检查(可以是每个函数调用)堆栈已经使用了多少,通过获取当前堆栈变量的地址。如果我们检测到可能的堆栈溢出,我们需要有一种方法来创建一个新的堆栈并链接到上一个堆栈。我想到的在C语言中实现这一点的唯一方法是创建一个新的线程来执行我们想要的函数,并在函数返回其结果之前锁定当前线程。

那么,是否有更清晰/更好的方法来实现这一点呢?

英文:

I was just reading about how Google Go makes each thread with a reduced stack size by default, and then links to new stacks if an overflow would occur ( see page 16 in here ). I was wondering the best way to do that in C.

I have to say I am no C expert, so there might be a better way to detect a Stack Overflow on C, but giving my ignorance, here's how I thought I would implement it:

The first thing I thought is that every time we have a fresh new stack, we get a stack variable's address, and with that we have roughly the starting stack address. Then we would need to be able to retrieve how much stack space the thread has. This would be possible if the thread isn't the main thread, but I have no idea how we would get this info on C.

Then we would need to check (per function call, it could be) how much of the stack is already used, by retrieving current stack variable address. If we detect a possible stack overflow, we would need to have some way to create a new stack and link to the last one. The only way I thought it could be done in C would be to create a new thread to execute the function we want, and lock the current thread until the function returns its result.

So, would there be a cleaner/better way to implement this?

答案1

得分: 9

请参阅GCC的split-stack功能。我相信这最初是为了支持Go而实现的。它基本上按照你的建议工作。

编辑:下面的评论讨论了另一个执行堆分配的系统。

英文:

See GCC's <a href="http://gcc.gnu.org/wiki/SplitStacks">split-stack capability</a>. I believe this was originally implemented to support Go. It pretty much works as you suggest.

EDIT: The commentary below discusses another system that does heap-allocation of activation records.

答案2

得分: 2

你可以这样做 - 我相信现代的gcc甚至可能有一个选项可以实现这个功能 - 但这会大大增加函数调用的成本,并且实际上几乎没有什么实际好处。特别是在具有64位寻址的现代系统上,每个线程都有足够的地址空间,使得每个线程的堆栈与其他线程的堆栈相隔很远。如果你发现自己使用的递归调用超过对数级别,那么你的算法肯定有问题...

英文:

You can do this - I believe modern gcc may even have an option for it - but it greatly increases the cost of function calls and has very little practical benefit. Especially on modern systems with 64-bit addressing, there's plenty of address space for each thread to have its own stack plenty far from every other thread's stack. If you find yourself using more than logarithmic-scale call recursion, something is wrong with your algorithms anyway...

huangapple
  • 本文由 发表于 2011年4月14日 11:05:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/5658087.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定