#include <stdio.h>
#include <stdlib.h>
#define _XOPEN_SOURCE 600
#include <ucontext.h>
/* Tests creation.
Should print "Hello World!" */
typedef struct thread_t{
ucontext_t thread_context;
}thread_t;
void *thr1(void *in) {
printf("Hello World!n");
fflush(stdout);
return NULL;
}
void *thr2(void *in) {
printf("goodbye World!n");
fflush(stdout);
return NULL;
}
int main() {
thread_t t1;
thread_t t2;
thread_create( &t1, thr1, NULL);
// if you comment out the following line, the program will run like a charm.
thread_create( &t2, thr2, NULL);
setcontext(&t1.thread_context);
return EXIT_SUCCESS;
}
void thread_routine(void *(*start_routine)(void *), void *arg)
{
start_routine(arg);
printf("gtthread routine finishedn");
}
int thread_create(thread_t *thread,
void *(*start_routine)(void *),
void *arg){
if (getcontext(&(thread->thread_context)) == -1)
{
perror("getcontext");
}
thread->thread_context.uc_stack.ss_sp = (char*) malloc(SIGSTKSZ);
thread->thread_context.uc_stack.ss_size = SIGSTKSZ;
thread->thread_context.uc_link = NULL;
makecontext(&(thread->thread_context), thread_routine, 2, (void *)start_routine, arg);
}
我运行我的代码在OS X 10.10与gcc。我正在尝试实现一个usercontext库。
如果我注释掉thread_create( &t2, thr2, NULL);
,代码将产生预期的效果。我不知道为什么与t2
相关的一行会导致t1
的分割故障。
我的猜测是,由于makecontext(), swapcontext()等在OS X上被弃用,因为编译器警告从10.6开始,我不应该期望它会工作。
标题>您的程序有一些缺陷,其中一些导致它产生未定义的行为。未定义的行为可以被证明是你所期望的行为,但是如果它在某个特定的环境中发生了一次,那就没有任何理由期望它会再次发生——在那个环境中不会,当然也不会在不同的环境中。
以下是我注意到的更严重的问题:
-
thread_routine()
对于上下文的开始函数没有正确的返回类型或参数类型。上下文启动函数预计返回void
(即没有)而不是void *
,这是完全不同的。此外,传递给它的实际参数(如果有的话)都将是类型int
。因此,当您的程序作为setcontext()
的结果调用此函数时,将导致未定义行为。在函数指针和对象指针的大小都与int
相同的机器上,您可以这样做,但在其他机器上,程序可能会严重崩溃。 -
在
thread_create()
中初始化thread->thread_context.uc_link
为NULL
。这本身并不是一个错误,但从更大的角度来看,当上下文的start函数返回时,它所运行的(OS)线程将退出。大概,您更希望有机会在不同的上下文中进行交换。 -
使用
setcontext()
切换到t1
上下文。如果成功,这个调用既不返回,也不返回,使您以后无法切换到t2
上下文。但实际上,当t1的start函数返回时,线程和整个程序都会退出(见上文),所以这对您来说没有意义。无论如何,您应该使用swapcontext()
。 -
thread_create()
声明返回int
,但是没有return
语句
gcc
应该对其中一些问题发出警告。如果没有,那么就调高警告级别。-Wall
级别应该是足够的,但我经常打开-Wextra
来寻找问题。偶尔会有可以忽略的警告(特别是-Wextra
),但是您应该对每个单独的警告分别进行评估。
我认为,你把"thread.h",为什么你使用线程如果你可以试试