c++ - 在 C++ 中使用 set_jmp/longjmp 不起作用

标签 c++ windows multithreading setjmp

我正在尝试在 c 中实现简单的用户级线程库。当一个线程启动并且该线程调用第二个线程时。这第二个线程运行正常,但当它退出时程序崩溃。这是我的编码。

//**********************************************
#include <setjmp.h>

typedef void *any_ptr;
/* Define Boolean type, and associated constants. */
typedef int Boolean;
typedef void (*ThreadFunc)(any_ptr);

#define TRUE ((Boolean)1);
#define FALSE ((Boolean)0);

typedef struct TheadSystem
{
  queue<any_ptr> readyQ;
  // currently executing thread
  jmp_buf lastContext; // location on which the system jumps after all threads have exited
  char name[30]; // optional name string of a thread, may be used for debugging
  jmp_buf context;   // saved context of this thread
  signal_t *sig; // signal that wakes up a waiting thread
  ThreadFunc func; // function that this thread started executing
  any_ptr    arg;
}TheadSystem;

void t_start(ThreadFunc f, any_ptr v, char *name);
void t_yield();
void block();
void unblock();
void t_sig(Condition cond, any_ptr val, Boolean queue_signal);
void t_fork(ThreadFunc f, any_ptr v, char *name);
void t_exit(int val);

我对threads.h的实现

#include "threads.h"
#include<iostream>
#include<queue>

using namespace std;
TheadSystem th;

queue<any_ptr> blocked_queue;
jmp_buf set_env,ready_env,yeild_buf;

void t_start(ThreadFunc f, any_ptr v, char *name){  
  if(!th.ready_queue.empty()){
    cout<<"sorry thread already started now you have to create by t_fork:"<<endl;
  }
  else{
    th.ready_queue.push(th.context);
      if(!setjmp(th.context)){
        memcpy(th.lastContext,th.context,sizeof(jmp_buf));
        th.arg=v;
        th.func=f;

        //memcpy(th.currentThread->context,set_env,sizeof(jmp_buf));
        //cout<<"when jmp buf set then:"<<endl;
        th.ready_queue.push(th.context);
        th.func(th.arg);
      }
    //cout<<"after come back from long jump:"<<endl;
  }
}

void t_yield(){
  jmp_buf *j=(jmp_buf *)th.ready_queue.front();
  th.ready_queue.front()=th.context;

  longjmp(*j,2);
}

void t_fork(ThreadFunc f, any_ptr v, char *name){
  memcpy(th.lastContext,th.context,sizeof(jmp_buf));
  if(!setjmp(th.context)){
    f(v);
    th.ready_queue.push(th.context);
  }else
  {
  }
}//end of t_fork

void t_exit(int val){   
  cout<<"before long jump in t_exit"<<endl;
  jmp_buf *j=(jmp_buf *)th.ready_queue.front();
  th.ready_queue.pop();
  longjmp(*j,2);    
}

void block(){
  blocked_queue.push(th.context);
  jmp_buf *j=(jmp_buf *)th.ready_queue.front();
  th.ready_queue.pop();
  longjmp(*j,2);    
}

void unblock(){
  th.ready_queue.push(th.context);
  jmp_buf *j=(jmp_buf *)blocked_queue.front();
  blocked_queue.pop();
  longjmp(*j,2);    
}

我的测试用例是

#include<iostream>
#include<setjmp.h>
#include<stdio.h>
#include "threads.h"
#include<queue>

using namespace std;    
void fun2(any_ptr v){
  cout<<"in 2nd function:"<<endl;
  t_exit(0);
}

void helloworld(any_ptr v){
  cout<<"in hello world from start"<<endl;
  t_fork(fun2,NULL,"no value");
  cout<<"after second thread:"<<endl;
  cout<<"before exit"<<endl;
  t_exit(0);
}

void main(){
  cout<<"1 start"<<endl;
  t_start(helloworld, NULL, "my function");
  cout<<"main function"<<endl;
}//end of void main

最佳答案

这是一个问题:

t_start 函数中,您可以这样做:

th.ready_queue.push(th.context);

ready_queue 是一个指针队列,但是th.context 不是指针。

然后在 t_yield 函数中做

jmp_buf *j=(jmp_buf *)th.ready_queue.front();

所以你压入非指针对象,并将它们作为指针弹出。如果您尝试将非指针对象作为指针访问,则您有 undefined behavior .

你的代码,如果编译没有错误,至少应该给你很多警告,如果你只得到几个警告,那么我建议你启用更多的警告。当编译器向您发出警告时,通常表示您正在做一些您不应该做的事情,比如做一些只会导致未定义行为的事情。只是通过例如使警告静音类型转换是一个非常糟糕的解决方案,因为它实际上并没有解决警告的原因。

此外,使用 void* 是坏代码出现的一个很好的标志。如果可以避免,请不要使用它,在这种情况下,在您使用它的大多数地方(例如 ready_queue)实际上不需要它。

关于c++ - 在 C++ 中使用 set_jmp/longjmp 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23357161/

相关文章:

c++ - 我如何单独创建和启动我的线程

c# - 终止一个线程运行我无法控制的代码

c++ - 从 void 指针缓冲区进行结构实例化

c++ - 如何在 C 或 C++ 中使用语句 block 定义函数?

linux - 没有在虚拟机中获得真正的文件更新

python - Windows 上的 Pocketsphinx-python 安装错误

multithreading - 在 akka scala Actor 中使用单例

C++ 枚举类作为可变模板参数

c++ - 不再满足条件后,while 循环会停止验证吗?

c++ - wcsdup 分配的内存是否应该显式释放?