gpt4 book ai didi

c - 有没有办法保存和恢复C中的调用堆栈

转载 作者:行者123 更新时间:2023-12-01 16:26:24 28 4
gpt4 key购买 nike

我想创建两个执行线程,执行两个不同的函数,然后使用相同的调用堆栈返回。执行不需要并行,执行线程可以依次执行。

我尝试使用setcontext/getcontext解决问题,但它们没有复制完整的调用堆栈,并且第二个线程无法使用第一个线程的调用堆栈:

#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>

ucontext_t fork_context, fork_context2;
char stack[SIGSTKSZ];
int end = 0;

void func2_1() {
printf("func2_1\n");
}


void func2_2() {
printf("func2_2\n");
end = 1;
}

void func2() {
printf("func2\n");
func2_1();

getcontext(&fork_context);
fork_context.uc_link = &fork_context2;
fork_context.uc_stack.ss_sp = stack;
fork_context.uc_stack.ss_size = sizeof(stack);
makecontext(&fork_context, (void (*)(void)) func2_2, 0);
}

void func1() {
printf("enter func1\n");
func2();
getcontext(&fork_context2);
printf("return func1\n");
}


int main(void) {
func1();
printf("back in main\n\n");

if (end != 1) {
setcontext(&fork_context);
}
return 0;
}

func2()中,我想执行func2_1(),然后根据调用堆栈返回。在从 main() 返回之前,我想执行 func2_2() 并返回到与从 func2_1() 返回时相同的函数。上面的代码产生以下输出:

func2_1
return func1
back in main

func2_2
return func1

func2_2()被正确调用,然后在func1()中继续执行,但func1()没有返回到main(),因为 func1() 调用的堆栈帧已被删除。我想要一个能产生以下输出的程序:

func2_1
return func1
back in main

func2_2
return func1
back in main

一种可能是使用 POSIX fork() 因为它复制整个过程(包括调用堆栈),但我不想使用 fork()如果可能的话。

最佳答案

我不禁认为 fork() 是此问题最简单的解决方案,尽管您可能需要一些共享内存才能合并两个调用的结果。 fork() 复制整个进程结构并不完全正确;它通常是通过单个虚拟内存页面的写时复制来实现的,因此它最终只会复制被修改的那部分状态;例如,不包括进程的代码。

如果你想自己做,你可以使用posix线程库的pthread_attr_setstack来创建一个具有特定堆栈的线程,你需要自己分配该堆栈。由于您可以控制堆栈内存,因此您可以自由地memcpy它以保留它。理论上,至少,您可以使用复制的堆栈创建另一个线程,并使用现已弃用的 getcontext 和 friend 来保存和恢复不在堆栈中的调用状态部分。为了有效地复制堆栈,您需要知道它的限制;有多种方法可以做到这一点,但它们都不是独立于平台的。

如果您想要提供 call/cc 的 C 实现,您可能想看看 Chicken Scheme ( http://www.call-cc.org ) 中的经典实现,它需要C 堆栈有很多有趣的自由,显然是成功的。

关于c - 有没有办法保存和恢复C中的调用堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23963423/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com