2014-10-17 67 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