Вы используете батут неправильно: вместо того, чтобы позволить ему вызывать вашу функцию thunk_f
, вы вызываете ее с результатом функции thunk_f
.
В результате, вы получаете переполнение стека. Вы можете избежать переполнения стека (но не бесконечного l oop), возвращая thunk_f
вместо его вызова:
void *thunk1(int *param)
{
++*param;
return thunk_f;
}
И вызывая trampoline
в main
правильно:
int main(int argc, char **argv)
{
int a = 4;
trampoline(thunk1, &a);
printf("%d\n", a);
}
И, конечно, для этого необходимо, чтобы trampoline
получил дополнительный аргумент, чтобы передать параметр &a
в:
void trampoline(void *(*func)(int *), int *arg) {
while (func) {
void *call = func(arg);
func = (void *(*)())call;
}
}
Это работает - но, как уже было отмечено, это просто бесконечный l oop без вывода. Чтобы увидеть, что происходит, поместите printf
внутри thunk1
:
void *thunk1(int *param)
{
printf("%d\n", ++*param);
return thunk_f;
}
Наконец, я, вероятно, должен отметить, что это неверно C, потому что преобразование между указателем объекта и функцией недопустимо указатель (всегда компилировать с предупреждениями pedanti c!). Чтобы сделать код легальным, оберните указатель функции в объект:
#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);
}