C-试图将字符传递到pthread_create,出现分段错误

C-试图将字符传递到pthread_create,出现分段错误,c,multithreading,segmentation-fault,pthreads,C,Multithreading,Segmentation Fault,Pthreads,好的,我已经创建了4个pthread(我正在创建4个线程,每个线程将管理一个基本方向,北、南、东或西): 我有我的threadcode函数 void *threadcode(void* dir) { char* direction; struct cart_t *cart = NULL; direction = (char*)dir; printf("casted direction %c\n", *direction); fprintf(stderr, "thread for direc

好的,我已经创建了4个pthread(我正在创建4个线程,每个线程将管理一个基本方向,北、南、东或西):

我有我的threadcode函数

void *threadcode(void* dir)
{
char* direction;
struct cart_t *cart = NULL;

direction = (char*)dir;

printf("casted direction %c\n", *direction);

fprintf(stderr, "thread for direction %c starts\n", *direction);
cart = q_getCart(*direction);
while (cart != NULL) {
    fprintf(stderr, "thread for direction %c gets cart %i\n",
        *direction, cart->num);
    monitor_arrive(cart);
    monitor_cross(cart);
    monitor_leave(cart);
    cart = q_getCart(*direction);
}
fprintf(stderr, "thread for direction %c exits\n", *direction);

return NULL;
}

由于某些原因,线程被创建,但在创建过程中,代码段出现了错误。我不确定它发生在哪里,但我非常确定它在threadcode函数中的某个地方,因为线程将开始创建,但随后将失败。

传递给
pthread\u create()
的内容会犯严重错误:

  • 它需要一个
    无效*
    。您正试图向其传递一个
    int
    。这是实现定义的行为,在某些情况下可能会明智地工作,但最好避免它。给它传递一个实际的指针

  • 如果确实传递了
    int
    ,那么至少应该在线程函数中将其转换回
    int
    。实际上,您试图将其转换为一个
    字符*
    ,它甚至与您所传递的内容都不接近。然后尝试取消引用该伪指针以获取字符,这就是为什么要分段

  • 这里有一个你应该做的例子。请注意,如果没有某种同步,您不应该在多个线程中调用
    printf()
    fprintf()
    之类的函数(或者
    perror()
    ,但对于一个简单的示例,无论如何它都会立即退出,我会抓住机会)。您没有显示实现,但是您正在调用的其他一些函数也有可能受到类似的保护

    #define _POSIX_C_SOURCE 200809L
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    pthread_mutex_t io_mtx = PTHREAD_MUTEX_INITIALIZER;
    
    void * threadcode(void * arg)
    {
        const char c = *((char *) arg);
    
        if ( pthread_mutex_lock(&io_mtx) != 0 ) {
            perror("couldn't acquire mutex");
            exit(EXIT_FAILURE);
        }
    
        printf("Entered thread for '%c'\n", c);
    
        if ( pthread_mutex_unlock(&io_mtx) != 0 ) {
            perror("couldn't release mutex");
            exit(EXIT_FAILURE);
        }
    
        return NULL;
    }
    
    int main(void)
    {
        pthread_t tidn, tids, tide, tidw;
        static char * dirs = "nsew";
    
        /*  Create threads  */
    
        if ( pthread_create(&tidn, NULL, threadcode, &dirs[0]) != 0 ) {
            perror("couldn't create north thread");
            return EXIT_FAILURE;
        }
        if ( pthread_create(&tids, NULL, threadcode, &dirs[1]) != 0 ) {
            perror("couldn't create south thread");
            return EXIT_FAILURE;
        }
        if ( pthread_create(&tide, NULL, threadcode, &dirs[2]) != 0 ) {
            perror("couldn't create east thread");
            return EXIT_FAILURE;
        }
        if ( pthread_create(&tidw, NULL, threadcode, &dirs[3]) != 0 ) {
            perror("couldn't create west thread");
            return EXIT_FAILURE;
        }
    
        /*  State that threads are created  */
    
        if ( pthread_mutex_lock(&io_mtx) != 0 ) {
            perror("couldn't acquire mutex");
            exit(EXIT_FAILURE);
        }
    
        printf("Threads created\n");
    
        if ( pthread_mutex_unlock(&io_mtx) != 0 ) {
            perror("couldn't release mutex");
            exit(EXIT_FAILURE);
        }
    
        /*  Join threads  */
    
        if ( pthread_join(tidn, NULL) != 0 ) {
            perror("couldn't join with north thread");
            return EXIT_FAILURE;
        }
        if ( pthread_join(tids, NULL) != 0 ) {
            perror("couldn't join with south thread");
            return EXIT_FAILURE;
        }
        if ( pthread_join(tide, NULL) != 0 ) {
            perror("couldn't join with east thread");
            return EXIT_FAILURE;
        }
        if ( pthread_join(tidw, NULL) != 0 ) {
            perror("couldn't join with west thread");
            return EXIT_FAILURE;
        }
    
        return 0;
    }
    

    非常感谢。我想如果所有其他方法都失败了,我会传入一个char*,但我希望有一种方法可以简单地将字符传递到线程函数中,而不创建整个变量。
    printf
    fprintf
    perror
    都保证在POSIX中是安全的。@caf:谢谢,你说得对。线程安全并不总是需要的全部——例如,输出仍然可能在多个调用之间随机交错,因此可能仍然需要手动同步——但是在这个我们只关心单个调用的特定程序中,正如你所说的,这很好。我真的很好奇为什么这里需要pthread_mutex_lock和pthread_mutex_unlock这样的调用?@Subhajit:正如caf所提到的,在这种特殊情况下,它们不适用于POSIX系统,因为库实现了类似的保护级别。但是所有这些调用都操纵一个静态内部缓冲区,而这些内部机制的不变量可能在调用中间被短暂失效。如果一个线程在另一个线程调用一个标准IO函数的同时调用一个标准IO函数,那么这些内部机制很快就会被搞乱。
    #define _POSIX_C_SOURCE 200809L
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    pthread_mutex_t io_mtx = PTHREAD_MUTEX_INITIALIZER;
    
    void * threadcode(void * arg)
    {
        const char c = *((char *) arg);
    
        if ( pthread_mutex_lock(&io_mtx) != 0 ) {
            perror("couldn't acquire mutex");
            exit(EXIT_FAILURE);
        }
    
        printf("Entered thread for '%c'\n", c);
    
        if ( pthread_mutex_unlock(&io_mtx) != 0 ) {
            perror("couldn't release mutex");
            exit(EXIT_FAILURE);
        }
    
        return NULL;
    }
    
    int main(void)
    {
        pthread_t tidn, tids, tide, tidw;
        static char * dirs = "nsew";
    
        /*  Create threads  */
    
        if ( pthread_create(&tidn, NULL, threadcode, &dirs[0]) != 0 ) {
            perror("couldn't create north thread");
            return EXIT_FAILURE;
        }
        if ( pthread_create(&tids, NULL, threadcode, &dirs[1]) != 0 ) {
            perror("couldn't create south thread");
            return EXIT_FAILURE;
        }
        if ( pthread_create(&tide, NULL, threadcode, &dirs[2]) != 0 ) {
            perror("couldn't create east thread");
            return EXIT_FAILURE;
        }
        if ( pthread_create(&tidw, NULL, threadcode, &dirs[3]) != 0 ) {
            perror("couldn't create west thread");
            return EXIT_FAILURE;
        }
    
        /*  State that threads are created  */
    
        if ( pthread_mutex_lock(&io_mtx) != 0 ) {
            perror("couldn't acquire mutex");
            exit(EXIT_FAILURE);
        }
    
        printf("Threads created\n");
    
        if ( pthread_mutex_unlock(&io_mtx) != 0 ) {
            perror("couldn't release mutex");
            exit(EXIT_FAILURE);
        }
    
        /*  Join threads  */
    
        if ( pthread_join(tidn, NULL) != 0 ) {
            perror("couldn't join with north thread");
            return EXIT_FAILURE;
        }
        if ( pthread_join(tids, NULL) != 0 ) {
            perror("couldn't join with south thread");
            return EXIT_FAILURE;
        }
        if ( pthread_join(tide, NULL) != 0 ) {
            perror("couldn't join with east thread");
            return EXIT_FAILURE;
        }
        if ( pthread_join(tidw, NULL) != 0 ) {
            perror("couldn't join with west thread");
            return EXIT_FAILURE;
        }
    
        return 0;
    }
    
    paul@horus:~/Documents/src/sandbox$ ./thread
    Entered thread for 'n'
    Entered thread for 's'
    Entered thread for 'w'
    Threads created
    Entered thread for 'e'
    paul@horus:~/Documents/src/sandbox$