为什么ucontext_t执行完成后未返回到uc_link指定的上下文?
问题根因
你代码的核心错误是协程栈内存分配在函数局部栈帧上,生命周期不匹配:
- 在
create_ctx函数中定义的char stack[STACK_SIZE]是当前函数的局部变量,存在于程序的调用栈上,当create_ctx执行结束返回后,这块内存会被系统自动回收,后续其他函数调用会直接覆盖这块地址的内容。 - 你给协程上下文的
uc_stack.ss_sp赋值为这个局部栈的地址,等于协程运行时用的是一块已经被释放的野内存,后续协程切换、执行过程中栈内容、uc_link等关键数据都会被意外篡改,行为完全未定义。 - 你观察到的退出码是19,是因为
routine2最后一次printf的返回值刚好存在rax寄存器中,上下文被破坏后程序异常跳转到了进程退出逻辑,直接把rax的值作为了进程退出状态码。
修复方案
协程的栈内存需要分配在堆上,保证在协程整个生命周期内都有效,修改create_ctx函数即可:
#include <stdio.h> #include <ucontext.h> #include <stdlib.h> typedef void (*coroutine_func)(); #define STACK_SIZE (1<<15) ucontext_t ctx_main; ucontext_t c1, c2; ucontext_t create_ctx(coroutine_func func, ucontext_t *ret_ctx) { ucontext_t ctx; getcontext(&ctx); // 堆分配协程栈,生命周期由自己管控 char *stack = malloc(STACK_SIZE); ctx.uc_stack.ss_sp = stack; ctx.uc_stack.ss_size = STACK_SIZE; ctx.uc_link = ret_ctx; makecontext(&ctx, func, 0); return ctx; } void routine1() { printf("routine1 running\n"); swapcontext(&c1, &c2); printf("routine1 returning\n"); } void routine2() { printf("routine2 running\n"); swapcontext(&c2, &c1); printf("routine2 returning\n"); } int main() { c1 = create_ctx(routine1, &ctx_main); c2 = create_ctx(routine2, &ctx_main); swapcontext(&ctx_main, &c1); swapcontext(&ctx_main, &c2); printf("main exiting.\n"); // 记得释放堆内存,避免泄漏 free(c1.uc_stack.ss_sp); free(c2.uc_stack.ss_sp); return 0; }
修复后运行结果:
routine1 running routine2 running routine1 returning routine2 returning main exiting. Process finished with exit code 0
内容的提问来源于stack exchange,提问作者rubys
相关产品推荐
相关产品推荐

