使用 pthreads 获取总线错误 10

Getting bus error 10 with pthreads

我的命令行工具不断抛出 bus error: 10 消息。 Xcode 调试器显示 EXC_BAD_ACCESS 消息并突出显示创建线程的函数调用。手动调试显示执行流在线程流内的随机位置中断。我尝试了另一个编译器(gcc),但结果是一样的。禁用 pthread_mutex_lock()pthread_mutex_unlock() 没有帮助。我写了这个重现错误的小例子。

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


typedef struct thread_args {
    pthread_mutex_t* mutex;
} thread_args;


void* test(void* t_args) {
    printf("Thread initiated\n");
    thread_args* args = (thread_args* )t_args;
    printf("Args casted\n");
    pthread_mutex_lock(args->mutex);
    printf("Mutex locked\n");
    pthread_mutex_unlock(args->mutex);
    printf("Mutex unlocked\n");
    pthread_exit(NULL);
}


int main() {
    pthread_mutex_t mutex1;
    pthread_mutex_init(&mutex1, NULL);

    thread_args args;
    args.mutex = &mutex1;

    pthread_t* thread;
    printf("Initiating a thread\n");
    pthread_create(thread, NULL, test, &args);
    return(0);
}

我认为,在你的情况下,

pthread_create(thread, NULL, test, &args);

在这个调用中,thread 是一个指针,没有分配内存。因此,本质上 pthread_create() 尝试写入未初始化的内存,这会创建 undefined behavior.

参考 pthread_create()

的手册页

Before returning, a successful call to pthread_create() stores the ID of the new thread in the buffer pointed to by thread;....

相反,您可以这样做

 pthread_t thread;
 ...
 pthread_create(&thread, NULL, test, &args);

您正在使用指向 pthread_t 的未初始化指针。 pthread_t 的实际存储需要在某个地方!

尝试:

int main() {
   pthread_mutex_t mutex1;
   pthread_mutex_init(&mutex1, NULL);

   thread_args args;
   args.mutex = &mutex1;

   pthread_t thread;
   printf("Initiating a thread\n");
   pthread_create(&thread, NULL, test, &args);
   return(0);
}

正如其他答案所指出的,您需要初始化您的指针 thread,您可以简单地这样做:

   pthread_t thread;
   pthread_create(&thread, NULL, test, &args);

Well, then I'll have to allocate memory dynamically, because different threads are spawned inside many different functions, hence I can't use local variables, because I'm not going to join the threads. Then, how can I free the allocated memory without waiting for the thread to finish, i.e. without calling join?

没有。您不需要仅仅因为要生成多个线程而动态分配。一旦线程被创建,线程标识符就不再需要了,所以它是局部变量还是 malloced 并不重要。仅当您需要 join 或更改线程的某些特征时才需要它——为此您需要 ID。否则,您甚至可以重用同一个线程来创建多个线程。例如,

   pthread_t thread;
   for( i = 0; i<8; i++)
     pthread_create(&thread, NULL, thread_func, NULL);

完全没问题。如果需要,线程始终可以通过调用 pthread_self() 来获取自己的 ID。但是你 不能 将局部变量 mutex1 传递给线程函数,因为一旦 main 线程退出, mutex1 不再退出,因为线程创建继续使用它。因此,您要么需要 malloc mutex1,要么将其设为全局变量。

另一件事是,如果您决定让主线程退出,那么您应该调用pthread_exit()。否则,当 main 线程退出时(通过调用 exit 或简单地 return),那么整个进程都会死掉,也就是说,所有线程也会死掉。