尝试将 swapcontext() 转换为存储在队列中的结构成员时出现段错误
Seg-fault when trying to swapcontext() into a struct member that is stored in a queue
我定义了一个名为 thread
的结构,其中包含一个名为 ucontext* tctx
的成员。
在一个名为 create_thread()
的函数中,我在堆上创建了一个线程对象并定义了它的每个成员(包括 ucontext 对象的成员)。然后我将指向该线程对象的指针添加到队列容器中。
当我弹出队列以交换到线程的上下文时,我发生了段错误。我不确定为什么会这样。
完整代码如下:
#include <iostream>
#include <queue>
#include <ucontext.h>
#define STACK_SIZE 262144
using namespace std;
typedef struct thread
{
int thread_id;
ucontext* tctx;
char* sp;
}thread;
int thread_id;
ucontext_t* ctx1; //Unused, currently
ucontext_t* cur;
queue<thread*> ready_queue;
/* Function Declaration */
thread* create_thread(int,int);
void foo1(int);
int main(int argc, char** argv)
{
cout << " PROGRAM START ***** \n";
/* Create 'i' number of threads */
for(int i = 0; i < 2; i++)
{
cout << "\nready_queue size before creating thread = " << ready_queue.size() << endl;
cout << "Calling create thread ... id=" << i << endl;
create_thread(i, i*1000);
cout << "ready_queue size after creating thread = " << ready_queue.size() << endl;
}
cout << " \t>> THREADS CREATED \n";
cout << " \t>> SWITCHING CONTEXT \n";
/* Save current context to cur, swap context to first thread in queue */
swapcontext(cur, ready_queue.front()->tctx); //Seg fault!
cout << " PROGRAM TERMI ***** \n";
return 0;
}
thread* create_thread(int id, int arg)
{
static int num_threads = 0;
/* Create a new thread struct, ucontxt for the thread, and put in ready queue */
thread* n = new thread;
getcontext(n->tctx);
n -> thread_id = id;
n -> tctx = new ucontext_t;
n -> sp = new char[STACK_SIZE];
n->tctx->uc_stack.ss_sp = n->sp;
n->tctx->uc_stack.ss_size = STACK_SIZE;
n->tctx->uc_stack.ss_flags = 0;
n->tctx->uc_link = NULL;
makecontext(n->tctx, (void(*)()) foo1, 1, arg); //Thread shall call foo() with argument 'arg'
/* Push new thread into ready_queue */
ready_queue.push(n);
num_threads++;
cout << "Thread #" << num_threads << " was created. Thread.ID[" << id << "]\n";
return n;
}
//Application function
void foo1(int arg)
{
cout << "Calling from foo1(). I have " << arg << "!\n";
}
已编辑:
我注意到如果我在 n -> tctx = new ucontext_t;
之后调用 getcontext(n->tctx);
问题就解决了。看来问题可能出在 getcontext
试图初始化堆中尚未分配的内容。
ucontext_t* cur
指针悬空,这就是它 swapcontext 崩溃的原因。您可以分配一个有效值 (new ucontext_t
),但最好将其类型设为 ucontext_t
而不是指针。 thread.tctx
也是如此,也没有必要保留 thread.sp
指针。
但是,C++11 有 std::thread
,这是比您尝试做的更好的替代方法,这将是正确的 C++ 方法。此外,如果您想学习新知识,我建议您转而关注 std::thread。这里有一个很好的教程:https://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/
顺便说一句,在你的例子中 getcontext(n->tctx);
也被调用了一个未初始化的 tctx
并且你在程序结束时有很多未释放的内存...
我定义了一个名为 thread
的结构,其中包含一个名为 ucontext* tctx
的成员。
在一个名为 create_thread()
的函数中,我在堆上创建了一个线程对象并定义了它的每个成员(包括 ucontext 对象的成员)。然后我将指向该线程对象的指针添加到队列容器中。
当我弹出队列以交换到线程的上下文时,我发生了段错误。我不确定为什么会这样。
完整代码如下:
#include <iostream>
#include <queue>
#include <ucontext.h>
#define STACK_SIZE 262144
using namespace std;
typedef struct thread
{
int thread_id;
ucontext* tctx;
char* sp;
}thread;
int thread_id;
ucontext_t* ctx1; //Unused, currently
ucontext_t* cur;
queue<thread*> ready_queue;
/* Function Declaration */
thread* create_thread(int,int);
void foo1(int);
int main(int argc, char** argv)
{
cout << " PROGRAM START ***** \n";
/* Create 'i' number of threads */
for(int i = 0; i < 2; i++)
{
cout << "\nready_queue size before creating thread = " << ready_queue.size() << endl;
cout << "Calling create thread ... id=" << i << endl;
create_thread(i, i*1000);
cout << "ready_queue size after creating thread = " << ready_queue.size() << endl;
}
cout << " \t>> THREADS CREATED \n";
cout << " \t>> SWITCHING CONTEXT \n";
/* Save current context to cur, swap context to first thread in queue */
swapcontext(cur, ready_queue.front()->tctx); //Seg fault!
cout << " PROGRAM TERMI ***** \n";
return 0;
}
thread* create_thread(int id, int arg)
{
static int num_threads = 0;
/* Create a new thread struct, ucontxt for the thread, and put in ready queue */
thread* n = new thread;
getcontext(n->tctx);
n -> thread_id = id;
n -> tctx = new ucontext_t;
n -> sp = new char[STACK_SIZE];
n->tctx->uc_stack.ss_sp = n->sp;
n->tctx->uc_stack.ss_size = STACK_SIZE;
n->tctx->uc_stack.ss_flags = 0;
n->tctx->uc_link = NULL;
makecontext(n->tctx, (void(*)()) foo1, 1, arg); //Thread shall call foo() with argument 'arg'
/* Push new thread into ready_queue */
ready_queue.push(n);
num_threads++;
cout << "Thread #" << num_threads << " was created. Thread.ID[" << id << "]\n";
return n;
}
//Application function
void foo1(int arg)
{
cout << "Calling from foo1(). I have " << arg << "!\n";
}
已编辑:
我注意到如果我在 n -> tctx = new ucontext_t;
之后调用 getcontext(n->tctx);
问题就解决了。看来问题可能出在 getcontext
试图初始化堆中尚未分配的内容。
ucontext_t* cur
指针悬空,这就是它 swapcontext 崩溃的原因。您可以分配一个有效值 (new ucontext_t
),但最好将其类型设为 ucontext_t
而不是指针。 thread.tctx
也是如此,也没有必要保留 thread.sp
指针。
但是,C++11 有 std::thread
,这是比您尝试做的更好的替代方法,这将是正确的 C++ 方法。此外,如果您想学习新知识,我建议您转而关注 std::thread。这里有一个很好的教程:https://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/
顺便说一句,在你的例子中 getcontext(n->tctx);
也被调用了一个未初始化的 tctx
并且你在程序结束时有很多未释放的内存...