pthread_create 的分段错误

Segmentation fault with pthread_create

我试图理解 C 中的 pthread 和 mutex。我想要两个人编写一个程序,计算给定值的平方并将其存储在给定大小的数组中。我想创建 4 个 pthreads 来计算每个值然后存储它们。所以我希望得到以下结果:[25] [25] ... [25],其中 x=5,a=10(数组大小)。 到目前为止我的代码是:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <error.h>

#define NTHREADS 4
static int k = 0;

struct thread_info{
    pthread_t thread_id;
    pthread_mutex_t lock;
    int x;
    int a[10];
};

void* fkt(void* arg){
    struct thread_info* tinfo = (struct thread_info*) arg;

    if(pthread_mutex_lock(&tinfo->lock)) perror("mutex_lock");

    printf("THREAD %d with argument %d\n", (int) tinfo->thread_id, tinfo->x);

    tinfo->a[k] = tinfo->x * tinfo->x;
    k++;

    if(pthread_mutex_unlock(&tinfo->lock)) perror("mutex_unlock");

    pthread_exit(NULL);
}

int main(){
    struct thread_info* tinfo = (struct thread_info*) malloc(sizeof(struct thread_info));

    tinfo->x = 5;

    if(pthread_mutex_init(&tinfo->lock, NULL)) perror("mutex_init");

    for(int i = 0; i < NTHREADS; i++){
        if(pthread_create(&tinfo[i].thread_id, NULL, &fkt, &tinfo)) perror("pthread_create");
    }   
    for(int i = 0; i < NTHREADS; i++){
        if(pthread_join(tinfo[i].thread_id, NULL)) perror("pthread_join");
        printf("THREAD JOINED: %d\n", (int) tinfo->thread_id);
    }   
    for(int i = 0; i < 10; i++){
        printf("[%d]\t", tinfo->a[i]);
    }   
    printf("\n");

    if(pthread_mutex_destroy(&tinfo->lock)) perror("mutex_destroy");

    return 0;
}

不幸的是,我遇到了分段错误,但我不明白为什么。 Valgrind 说 "Invalid write of size 4" 那句话是什么意思?

编辑:我从主函数的 tinfo 声明中删除了 NULL。仍然遇到 valgrind 的分段错误。执行二进制文件似乎 运行 无限。

Unfortunately I get a segmentation fault and I dont see why.

不难看出原因:程序开头的这两行保证了这一点:

struct thread_info* tinfo = NULL;
tinfo->x = 5;

第二行尝试写入(取消引用)在第一行创建的 NULL 指针。

你应该学会使用调试器,这样你就不会被这些微不足道的错误难倒了。

(你的程序可能还有其他bug,我没看。)

更新:

现在您已经纠正了第一个问题,但引入了一个新问题:此行分配 space 给 one thread_info:

struct thread_info* tinfo =
  (struct thread_info*) malloc(sizeof(struct thread_info));

但是对于 0 以上 i 的所有值,此行溢出该缓冲区:

for(int i = 0; i < NTHREADS; i++){
    if(pthread_create(&tinfo[i].thread_id, ...

我认为您在调用 pthread_create 时可能还错误地传递了指向线程目标函数参数的指针。由于变量 tinfo 在您的 main 函数中是 malloc,它已经是一个指针。但是,当您将目标函数的参数传递给 pthread_create 时,您传递的是 &tinfo,它的类型实际上是 struct thread_info **。也就是说,它不是指向 struct thread_info 的指针,而是可以取消引用一次以获得指向 struct thread_info 的指针的指针。这会导致问题,因为 fkt 将此指针视为 struct thread_info *,这是不正确的。我敢打赌,在您对 pthread_create 的调用中将 &tinfo 替换为 tinfo 将有助于解决问题。