【问题标题】:Getting bus error 10 with pthreads使用 pthread 获取总线错误 10
【发布时间】:2015-06-23 19:38:04
【问题描述】:

我的命令行工具不断抛出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);
}

【问题讨论】:

    标签: c multithreading debugging pthreads


    【解决方案1】:

    我认为,在你的情况下,

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

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

    参考pthread_create()的手册页

    在返回之前,对pthread_create()的成功调用会将新线程的ID存储在thread所指向的缓冲区中;....

    相反,你可以这样做

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

    【讨论】:

    • 我一直认为这是导致segmentation fault的错误
    • @EliKorvigo 很好,几乎,但并非总是如此。 UB 是实际效果,segfault 是副作用。
    • 好吧,那我就得动态分配内存了,因为在很多不同的函数中产生了不同的线程,所以我不能使用局部变量,因为我不会去join线程。那么,我如何free分配的内存而不等待线程完成,即不调用join
    【解决方案2】:

    您正在使用指向您的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);
    }
    

    【讨论】:

      【解决方案3】:

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

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

      那么,我将不得不动态分配内存,因为不同 线程在许多不同的函数中产生,因此我不能使用 局部变量,因为我不打算加入线程。那么,如何 我可以释放分配的内存而不等待线程 完成,即不调用加入?

      没有。您不需要仅仅因为要产生多个线程而动态分配。一旦创建了线程,就不再需要线程标识符所以它是局部变量还是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),那么整个进程都会死掉,也就是说,所有线程也会死掉。

      【讨论】:

      • 由于我总是避免使用全局变量,因此互斥锁确实在 main 函数中声明,并通过 thread_args 实例作为指针传递。 main 函数等待所有线程完成它们的工作,所以没关系。很高兴知道pthread_p 实例仅用于启动线程一次。谢谢。
      • @EliKorvigo 请注意关于pthread_exiting 的另一点也在 main 中。否则,它的行为将不会如您所愿。
      猜你喜欢
      • 2016-07-14
      • 1970-01-01
      • 2017-07-06
      • 2013-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-15
      • 2011-12-14
      相关资源
      最近更新 更多