gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-28 00:29:53 27 4
gpt4 key购买 nike

我正在尝试在 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/

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