2014-07-25 75 views
1

我有一個應該啓動線程的程序。爲了避免退出軟件,線程以無限循環運行,並加入線程。這個線程永遠不會返回一個值。所以現在我有問題,我調用pthread_cancel valgrind檢測到內存泄漏。我怎樣才能避免這種內存泄漏?如何通過使用pthread_cancel來避免內存泄漏?

Valgrind的輸出:

==5673== 136 bytes in 1 blocks are possibly lost in loss record 4 of 8 
==5673== at 0x4026A68: calloc (vg_replace_malloc.c:566) 
==5673== by 0x40111FB: _dl_allocate_tls (dl-tls.c:300) 
==5673== by 0x404E5A0: [email protected]@GLIBC_2.1 (allocatestack.c:580) 
==5673== by 0x804C44E: start (mythread.c:25) 
==5673== by 0x804D128: main (main.c:10) 

代碼:

int main(){ 
    signal(SIGINT,cleanup); 
    signal(SIGQUIT,cleanup); 
    signal(SIGSEGV,cleanup); 
    start(); 
    return 0; 
} 

int start() 
{ 
    pthread_create(&thread_id[0],NULL,&threadhandler,NULL); 
    pthread_join(thread_id[0],NULL); 
    return err; 
} 

void cleanup(){ 
    pthread_cancel(thread_id[0]); 
    exit(0); 
} 

void cleanup_tcp(void *p){ 
} 


void* threadhandler(void *arg) 
{ 
    (void) arg; 
    int status = 0; 
    while(TRUE){ 
     pthread_cleanup_push(cleanup_tcp,NULL); 
     pthread_testcancel(); 
     fprintf(stderr,"Run\n"); 
     pthread_cleanup_pop(0); 
    } 
    return NULL; 
} 
+1

拆卸螺紋(通過調用'pthread_detach()')取消它可以幫助(位)之前。 – alk

回答

1

你已經正確識別使用pthread_cancel()的缺點:由線程清理例程釋放也將隨之泄露尚未發佈任何資源/。就你而言,看起來線程庫本身可能已經分配了一些未被釋放的內存。

一個更好的方法,國際海事組織,將創建一個機制,通知threadhandler線程,它應該終止。例如

static volatile sig_atomic_t done = 0; 
... 
void cleanup() 
{ 
    done = 1; 
} 

void* threadhandler(void* arg) 
{ 
    while (!done) 
     fprintf(stderr, "Run\n"); 
    return NULL; 
} 
+0

'揮發性'是多餘的和有害的。使用一個原子變量就足夠了。 – cmaster

+0

@cmaster我不同意。 X/Open規範明確引用了'volatile'限定符:「如果信號不是由於調用abort(),raise(),[CX] [Option Start] kill(),pthread_kill()或sigqueue (),[Option End]如果信號處理程序引用具有靜態存儲持續時間的任何對象,而不是通過爲聲明爲volatile的sig_atomic_t,...分配值的對象,則行爲未定義。此外,「此參考頁上描述的功能與ISO C標準一致」。 –

+0

好吧,可能我對X/Open不夠了解,我根據C標準的條件來判斷,假設'sig_atomic_t'是一個與C標準定義爲原子的類型相同的類型。如果是這樣的話,那麼'volatile'就沒用了。但是現在看來,X/Open規範是在C標準定義的原子類型之前編寫的,所以現在我想'volatile'確實需要與'sig_atomic_t'結合使用。不過,我會建議使用當前C標準的原子類型。 – cmaster