C++ 带有Pthreads的Hello World内存已损坏
我正在学习llnl.computing.gov pthreads教程中的一些简单pthread示例。网站上的程序会打印出线程id的地址,但我想将id的地址传递给PrintHello,然后使用解引用地址来获取id。我认为在睡眠中,每个线程都应该打印8(线程数)。代码是C++ 带有Pthreads的Hello World内存已损坏,c++,c,pthreads,segmentation-fault,C++,C,Pthreads,Segmentation Fault,我正在学习llnl.computing.gov pthreads教程中的一些简单pthread示例。网站上的程序会打印出线程id的地址,但我想将id的地址传递给PrintHello,然后使用解引用地址来获取id。我认为在睡眠中,每个线程都应该打印8(线程数)。代码是 #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define NUM_
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_THREADS 8
void *PrintHello(void *threadid)
{
long *taskid = (long *)threadid;
sleep(1);
printf("Hello from thread %ld\n", *taskid);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0;t<NUM_THREADS;t++) {
printf("Creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) &t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
它没有seg错误,它只是打印地址,我想取消对地址的引用,从main获取t的值
有人对如何实现这一目标有什么建议吗?我知道我可以将
t
传递给pthread\u create
而不是&t
,但出于学习目的,我想这样做。当您从主线程调用pthread\u exit(NULL)
时,它会终止该线程。此时,main
函数中的任何局部变量(包括t
)都将被销毁,无法再使用
如果主线程在使用t
完成所有工作线程之前退出(通过pthread\u create
传递给它们的指针),则程序将显示未定义的行为
程序包含争用条件,因为从工作线程访问变量t
和从主线程销毁变量t
是不同步的。解决此问题的一种方法是让主线程在退出前与每个工作线程连接(通过pthread\u join
)。1)传递t
的地址,这样每个线程都会得到一个指向同一个变量的指针,该变量不是线程ID,而是一个长的,其值不断变化。您正在修改main
中的变量,并在其他线程中读取它,这是一种数据竞争
2) 可能发生的情况是,当新线程在main
中执行循环时,该变量已超出范围。当main
退出时,其局部变量将从堆栈中弹出,因此当其他线程访问t
时,它不再在堆栈中。您的程序中没有任何同步来防止这种情况,因此您在那里有另一个数据竞争。您需要在main
中等待线程完成,您可以通过调用pthread\u join
来等待每个线程,但这仍然不会改变其他线程在另一个线程写入变量时试图读取该变量的事实
3) 不需要在那里调用pthread\u exit
,从函数返回或从main自动退出线程(就像调用exit(0)
导致main()
完成)一些指针?嗯,你的线程函数中有很多这样的函数
问题是:您无法安全地传递局部变量的地址-当main退出时,它会超出范围。您需要将指针声明为静态全局变量,或者将内存的malloc()sizeof(long)字节声明为静态全局变量并使用它。Btw:主线程的终止不会停止所有其他线程吗?@H2CO3,我相信如果其他线程仍在运行,调用pthread\u exit
不会终止整个进程。调用exit
或从main
返回将导致整个进程停止,即使其他线程正在运行,但当调用pthread\u exit
时,该进程仅在它是最后一个线程时才退出。虽然main中的pthread\u exit
不会终止整个进程,但变量t
仍然超出范围并从堆栈中弹出。这是有意义的。如果我传递值t
,它就会起作用,因为每个线程都有自己的t
副本,当Main
执行时,它不会消亡?对,当您通过值传递某个内容时,您会制作一个副本供被调用方使用。当您传递指针时,指针本身是按值传递的,但是在调用者和被调用者中指向的东西是相同的。即使您同步它们,它也不会执行您可能想要的操作。所有线程都可能打印相同的数字,因为它们使用相同的变量。打印的值将取决于日程安排
void *PrintHello(void *threadid)
{
long taskid = (long) threadid;
sleep(1);
printf("Hello from thread %ld\n", taskid);
pthread_exit(NULL);
}