2012-08-08 56 views
0

剛剛遇到了有關如何將第四個參數傳遞給pthread_create()的奇怪問題。指向pthread_create()的最後一個參數的指針導致崩潰

本來,我寫的代碼如下:

auditLogEntry *newEntry = NULL; 

// malloc and init the memory for newEntry 
rc = audit_init_log_entry(&newEntry); 
// wrapper of 'goto cleanup' 
ERR_IF(rc != 0); 
... 
rc2 = pthread_attr_init(&attr); 
ERR_IF(rc2 != 0); 
rc2 = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 
ERR_IF(rc2 != 0); 
rc2 = pthread_create(&syslog_thread, &attr, syslog_thread_handler, (void *)newEntry); 
ERR_IF(rc2 != 0); 
newEntry = NULL; 
... 
cleanup: 
pthread_attr_destroy(&attr); 
if (newEntry != NULL) 
{ 
    audit_free_log_entry(newEntry); 
    newEntry = NULL; 
} 

static void *syslog_thread_handler(void *t) 
{ 
    auditLogEntry *entry = (auditLogEntry *)t; 
    ... // code using entry 
    cleanup: 
    audit_free_log_entry(entry); 

    pthread_exit(0); 
} 

,一切工作正常。

於是,我做了一個變化:

rc2 = pthread_create(&syslog_thread, &attr, syslog_thread_handler, (void *)&newEntry); 
ERR_IF(rc2 != 0); 
... 
cleanup: 
pthread_attr_destroy(&attr); 
if (rc != 0 && newEntry != NULL) 
{ 
    audit_free_log_entry(newEntry); 
    newEntry = NULL; 
} 

static void *syslog_thread_handler(void *t) 
{ 
    auditLogEntry **entry = (auditLogEntry **)t; 
    ... // code using *entry 
    cleanup: 
    audit_free_log_entry(*entry); 
    *entry = NULL; 

    pthread_exit(0); 
} 

線程處理器將使用*進入訪問日誌條目數據,上述變更後。但它沒有奏效。更糟糕的是,流程核心傾倒。

我試過'man pthread_create',但沒有發現如何將最後一個參數傳遞給它。

我的任何錯誤,在這裏?

+0

所以爲什麼要改變呢?它在一開始就工作正常,這是一個明智的做事方式。如果它有效,那麼改變它的原因是什麼? – mathematician1975 2012-08-08 15:21:06

+0

@ mathematician1975:我想回收線程處理程序中的內存,然後將*條目設置爲NULL。所以父進程不會有雙入口指針的危險。 – 2012-08-08 15:35:22

+0

好吧,你的問題並不完全清楚。 – mathematician1975 2012-08-08 15:50:01

回答

2

您不顯示完整的代碼,因此很難說出發生了什麼。

但是,&newEntry爲您提供了一個指向棧上變量的指針。如果newEntry超出範圍,例如因爲你的函數結束了,你的另一個線程現在有一個無效指針 - 指向堆棧中現在已經消失的地方。並且取消引用這樣的指針會導致未定義的行爲。

int *foo(void) 
{ 
    int x = 2; 
    return &x; 
} 

void bar(void) 
{ 
    int *x = foo(); 
    printf("%d\n", *x); //can't do this, x points to something 
         //on the stack in the foo function, 
         //which isn't valid any more 
} 

你有同樣的問題,如果把foo()函數傳遞&x給它創建的線程。

void foo(void) 
{ 
    int x = 2; 
    ... 
    pthread_create(&tid, bar, NULL, &x); 
} 

無效*巴(無效* ARG) { INT * X =精氨酸;

printf("%d\n", *x); //same problem here, x points to something 
         //on the stack in the foo function, which isn't valid 
         //if the foo function ends. This concept is exactly the same 
         //if x had been a pointer inside the foo() function. 
} 

這裏也許您的方案:

int globalx = 2; //global variable 
void foo(void) 
{ 
    int *x = malloc(sizeof(int)); 
    ... 

    pthread_create(&tid, bar, NULL, &x); //we're still taking the address of 
             //a local variable. 
} 

void *bar(void *arg) 
{ 
    int **x = arg; 
    printf("%p\n", *x); //still the same problem here, x points to something 
         //on the stack in the foo function, which isn't valid 
} 
+0

newEntry本身應該沒有問題,它通過'malloc()'分配在堆中,無論如何,我會嘗試在場景中添加更多的代碼 – 2012-08-08 21:56:33

+1

@Qiang Xu這並不重要,'auditLogEntry * newEntry = ....;'在堆棧中,當然,它可能指向堆上的東西,但newEntry變量在堆棧中。執行'&newEntry'會爲您提供一個指向該堆棧上的變量的指針。把指針看作2件事。有指針變量,指針指向的是事物。 – nos 2012-08-08 21:59:32

0

無論核心轉儲來自哪裏,都不是來自pthreads。你對最後的論點所做的事絕對沒問題。

+0

真的嗎?但是這是生命與死亡之間唯一的區別,:( – 2012-08-08 21:47:57

相關問題