2014-10-17 66 views
0

好的,所以我有4个线程创建(我创建了4个线程,每个线程都管理一个基本方向,北,南,东或西):C-尝试将字符传递到pthread_create,发生分段错误

if ((rc = pthread_create(&tidn, NULL, threadcode, (void *)'n')) != 0) 
    fprintf(stderr, "thread create failed (%s)\n", strerror(rc)), exit(1); 
if ((rc = pthread_create(&tids, NULL, threadcode, (void *)'s')) != 0) 
    fprintf(stderr, "thread create failed (%s)\n", strerror(rc)), exit(1); 
if ((rc = pthread_create(&tide, NULL, threadcode, (void *)'e')) != 0) 
    fprintf(stderr, "thread create failed (%s)\n", strerror(rc)), exit(1); 
if ((rc = pthread_create(&tidw, NULL, threadcode, (void *)'w')) != 0) 
    fprintf(stderr, "thread create failed (%s)\n", strerror(rc)), exit(1); 

,我有我的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函数中的某处,因为线程将开始创建,但会失败。

回答

1

你正在做的严重错误与你传递给pthread_create()什么:

  1. 它需要一个void *。你正试图通过它int。这是实现定义的行为,并且在某些情况下可能可能明智地工作,但最好避免它。传递一个实际的指针。

  2. 如果传递一个int,那么你至少应该将其转换回一个int在你的线程功能。你实际上试图转换成一个char *,它甚至不是接近你传递的。然后,您尝试取消引用虚假指针来获取角色,这就是为什么您要进行分段转换。

下面是你应该做的一个例子。请注意,您不应该在多线程中调用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; 
} 

可能的输出:

[email protected]:~/Documents/src/sandbox$ ./thread 
Entered thread for 'n' 
Entered thread for 's' 
Entered thread for 'w' 
Threads created 
Entered thread for 'e' 
[email protected]:~/Documents/src/sandbox$ 
+0

谢谢!我想如果一切都失败了,我会传入一个char *,但我希望有一些方法可以简单地将字符传递给线程函数,而不需要创建一个完整的变量。 – mike10010100 2014-10-17 22:45:59

+0

'printf','fprintf'和'perror'都保证在POSIX中是安全的。 – caf 2014-10-18 09:22:17

+0

@caf:谢谢,你是对的。线程安全并不总是需要的 - 例如输出仍然可以在多次调用之间随机交错,因此手动同步可能仍然是必需的 - 但在这个特定的程序中,我们只关心个别调用,那么按照您所说的那样就可以。 – 2014-10-18 12:35:33