[英]Avoiding stack overflow using a trampoline
The trampoline function in the program below works properly.下面程序中的蹦床function工作正常。 I think the program below results in stack overflow because the functions thunk_f and thunk1 call each other indefinitely, resulting in the creation of new stack frames.
我认为下面的程序会导致堆栈溢出,因为函数 thunk_f 和 thunk1 无限期地相互调用,从而导致创建新的堆栈帧。 However, I want to write a program that behaves more similarly to a nonterminating loop, as trampolines should prevent stack overflow.
但是,我想编写一个行为更类似于非终止循环的程序,因为蹦床应该防止堆栈溢出。
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
void trampoline(void *(*func)()) {
while (func) {
void *call = func();
func = (void *(*)())call;
}
}
void *thunk1(int *param);
void *thunk_f(int *param);
void *thunk1(int *param)
{
++*param;
trampoline(thunk_f(param));
return NULL;
}
void *thunk_f(int *param)
{
return thunk1(param);
}
int main(int argc, char **argv)
{
int a = 4;
trampoline(thunk1(&a));
printf("%d\n", a);
}
You are using the trampoline incorrectly: rather than letting it invoke your thunk_f
function, you call it with the result of the thunk_f
function.您错误地使用了蹦床:与其让它调用您的
thunk_f
function,不如使用thunk_f
function 的结果调用它。
As a result, you are getting a stack overflow.结果,您会遇到堆栈溢出。 You can avoid the stack overflow (but not the infinite loop) by returning
thunk_f
instead of calling it:您可以通过返回
thunk_f
而不是调用它来避免堆栈溢出(但不是无限循环):
void *thunk1(int *param)
{
++*param;
return thunk_f;
}
And calling trampoline
in main
correctly:并在
main
中正确调用trampoline
:
int main(int argc, char **argv)
{
int a = 4;
trampoline(thunk1, &a);
printf("%d\n", a);
}
And of course this requires that trampoline
gets an additional argument, to pass the &a
parameter on:当然,这需要
trampoline
获得一个额外的参数,以传递&a
参数:
void trampoline(void *(*func)(int *), int *arg) {
while (func) {
void *call = func(arg);
func = (void *(*)())call;
}
}
This works — but as noted, it's just an infinite loop without output.这可行——但如前所述,它只是一个没有 output 的无限循环。 To see what's happening, put the
printf
inside thunk1
:要查看发生了什么,请将
printf
放入thunk1
:
void *thunk1(int *param)
{
printf("%d\n", ++*param);
return thunk_f;
}
Lastly, I should probably note that this is invalid C, because it's illegal to convert between a object pointer and a function pointer (always compile with pedantic warnings.), To make the code legal: wrap the function pointer into an object: Lastly, I should probably note that this is invalid C, because it's illegal to convert between a object pointer and a function pointer (always compile with pedantic warnings.), To make the code legal: wrap the function pointer into an object:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
struct f {
struct f (*p)(void *);
};
void trampoline(struct f f, void *args) {
while (f.p) {
f = (f.p)(args);
}
}
struct f thunk1(void *param);
struct f thunk_f(void *param);
struct f thunk1(void *param) {
printf("%d\n", ++*((int *) param));
return (struct f) {thunk_f};
}
struct f thunk_f(void *param) {
return thunk1(param);
}
int main() {
int a = 4;
trampoline((struct f) {thunk1}, &a);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.