我有一个关于使用 setjmp 和 longjump 来创建可以相互独立运行的函数堆栈的问题。引用this question
此处 B() 的函数堆栈似乎位于 A 的函数堆栈之上,因此当 A 超出范围并且我尝试长跳转到 B() 时,代码出现段错误。修改后的代码是这样的
#include <stdio.h>
#include <setjmp.h>
#include <iostream>
using namespace std;
jmp_buf bufferA, bufferB;
void routineB(); // forward declaration
void routineA()
{
int r ;
printf("(A1)\n");
r = setjmp(bufferA);
if (r == 0) routineB();
printf("(A2) r=%d\n",r);
r = setjmp(bufferA);
if (r == 0) longjmp(bufferB, 20001);
printf("(A3) r=%d\n",r);
r = setjmp(bufferA);
if (r == 0) longjmp(bufferB, 20002);
printf("(A4) r=%d\n",r);
}
void routineB()
{
int r;
printf("(B1)\n");
r = setjmp(bufferB);
if (r == 0) longjmp(bufferA, 10001);
printf("(B2) r=%d\n", r);
r = setjmp(bufferB);
if (r == 0) longjmp(bufferA, 10002);
printf("(B3) r=%d\n", r);
r = setjmp(bufferB);
if (r == 0) longjmp(bufferA, 10003);
cout << "WHAT" << endl;
}
int main(int argc, char **argv)
{
routineA();
longjmp(bufferB, 123123);
return 0;
}
我在想,我们可以让每个协程(在本例中为 B 和 A)跳回一个主函数,然后跳转到其中一个协程,前提是它们还活着。这会起作用还是会出现段错误,因为一些可能已死亡的协程堆栈位于想要运行的协程堆栈之上?
如果它看起来确实应该出现段错误,那么如何在 C++ 中实现这样的独立协程(它们可以在其他协程死亡并且不依赖彼此时运行)?
注意:我不想使用 swapcontext、makecontext、setcontext 和 getcontext,因为它们已被弃用。这篇文章的目的是帮助我找到这些功能的替代品
提前致谢!
最佳答案
它应该可以工作,但需要采取一些预防措施。它曾经在九十年代工作。
只要堆栈中较旧的线程不返回,它就可以工作,那么应该没有问题。对于生成器或线程,这意味着它以一些最终 yield 终止,但没有返回。
我记得我要求 IBM 修复他们的 setjmp/longjmp 的 AIX 实现,以便它停止检查(并禁止)其他实现允许的有用行为。这是我当时发现的实现协作线程的最便携方式。
您可以使用基于状态机的堆栈分配器做得更好,以便为不同的线程分配/释放不同大小的堆栈。
据我所知,这非常棘手。我记得多年后 Matz(来自 Ruby)问我关于它的代码,但遗憾的是我当时无法访问它。
无论如何,现在这并不重要,因为 pthread 完成了这项工作。
关于c++ - setjmp 和 longjump 实现线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33408007/