Linux程式設計中由線程使用不當引起的記憶體流失

來源:互聯網
上載者:User

Linux程式設計中由線程使用不當引起的記憶體流失

作者:吳亮

 

Linux程式設計中,建立線程時調用pthread_create()函數,該函數原型如下:

 

int pthread_create(

pthread_t *thread,

const pthread_attr_t *attr,

void *(*start_routine)(void*),

void *arg);

 

其中第二個參數attr為線程屬性指標,一般情況下,我們建立線程時,若對線程屬性沒有特殊要求,都將此參數設為NULL。這也就使用了線程的預設屬性——非分離狀態(joinable,或稱可接合狀態)。之後,主線程必須在適當的時候調用pthread_join(),來接合(join,或等待,同步)子線程,同時釋放線程本身佔用的資源。否則,線程資源將駐留記憶體,直到整個進程退出為止,若進程會不斷的建立線程,則每建立一次線程都會導致記憶體資源的消耗,很明顯,這樣就會構成記憶體流失!

 

關於這個問題,本人查到了一些佐證:

(1)Linux manpage裡是這樣講的:

 When a joinable threadterminates, its memory resources (thread descriptor and stack) are notdeallocated until another thread performs pthread_join on it. Therefore,pthread_join must be called  once  for each joinable thread created to avoid memory leaks.

 

(2)《Linux進階編程》裡是這樣講的:

可接合(非分離態的,需要等待)的線程,就像一個進程一樣,當它執行結束時,並沒有被GNU/Linux自動清理,而它的退出狀態卻仍在系統內掛著(這有點像殭屍進程),直到另一個線程調用pthread_join()擷取其傳回值時,其資源才被釋放。

 

* * * * * * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

 

對於線程資源的釋放,有兩種實現方法:

(1)調用pthread_join()

線程建立時,預設屬性是可接合的(joinable),那就需要主線程來等待,所以在建立這個線程後適當的時候就必須調用pthread_join()來等待子線程結束執行,否則就會引起記憶體流失!

 

在調用pthread_create()開線程後,若線程屬性是joinable,則必須調用pthread_join()來等待子線程結束執行,這是 Linux同步主線程和子線程的一個機制,但是,這並不等於說,我要在pthread_create()開線程後立即調用pthread_join()來等待該線程結束執行,的確,那樣的話跟你用普通函數調用來實現是沒有區別的,你完全可以在pthread_create()開線程後去做別的事情,等你覺得應該等待該線程結束執行時再調用pthread_join()。這就是說,假如你的線程採用了預設屬性joinable,你就必須在適當的時候調用pthread_join()來同步主線程和子線程,同時釋放子線程的資源(線程描述符和堆棧,threaddescriptor
and stack)。

假如你用了預設線程屬性,即線程屬性為joinable,而又沒有在適當的時候調用pthread_join(),那麼該線程所佔用的資源便不會被釋放(kind of like azombie process),因此造成記憶體流失。

 

(2)將線程屬性設為分離狀態(detached)

假如你不想或沒有必要同步主線程和子線程,那麼就把子線程屬性設定為detached分離狀態,那麼子線程結束執行後會自行銷毀其佔用的資源。

將線程屬性設為分離狀態(detached),這樣,子線程就屬於自我銷毀那種,子線程函數啟動後跟主線程不再有"父子"關係(等待和被等待),退出線程時其資源會釋放。注意:建立線程時,若屬性參數為NULL,則線程屬性預設為可接合的(joinable,即需要主線程等待的)。

可以線上程建立時將其屬性設為分離狀態(detached),也可線上程建立後將其屬性設為分離的(detached)。

 

* * * * * * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

 

下面給出分離態和非分離態線程建立的代碼架構:

 

(1)使用線程預設屬性建立線程的代碼架構

#include <pthread.h>

void* thread_function (void* thread_arg)

{

/* Do work here... */

pthread_exit(“Exiting from the thread_function!”);

}

 

int main ()

{

pthread_t thr;

void* thread_result;

pthread_create (&thr, NULL, &thread_function, NULL);

 

/* Do other work here... */

 

/* The second thread must be joined by the initial(calling) thread before exit or elsewhere

to avoid MEMORY LEAKS

*/

pthread_join(thr, &thread_result);

return 0;

}

 

 

 

(2)將線程屬性設為detached的兩種方法的代碼架構

方法一,線上程建立時,通過屬性變數設定

#include <pthread.h>

void* thread_function (void* thread_arg)

{

/* Do work here... */

pthread_exit(….);

}

 

int main ()

{

pthread_attr_t attr;

pthread_t thread;

 

pthread_attr_init (&attr);

pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);

pthread_create (&thread, &attr, &thread_function, NULL);

pthread_attr_destroy (&attr);

 

/* Do work here... */

/* No need to join the second thread. */

return 0;

}

 

 

方法二:線程建立後,通過調用pthread_detach()來設定

注意:

如果thread_function()做的工作足夠少的話,在pthread_create()返回線程ID前,thread_function()可能就已經結束了,而這個線程ID可能又被系統分配給了新建立的線程,假如新線程不打算使用分離態,那下面的pthread_detach()調用就會引起錯亂,實際上原來要設為分離態的線程並沒有設為分離態,假如再沒有調用pthread_join()的話(實際上也不會,因為調用了pthread_detach()就不該再調用pthread_join(),而且此時join的實際上是新線程),那就會導致該線程的資源不被釋放,而又引起記憶體泄露。所以在這兒,pthread_detach()的調用還是需要綜合考量的。

#include <pthread.h>

void* thread_function (void* thread_arg)

{

/* Do work here... */

pthread_exit(….);

}

 

int main ()

{

pthread_t thread;

 

pthread_create (&thread, NULL, &thread_function, NULL);

pthread_detach(thread);

 

/* Do work here... */

/* No need to join the second thread. */

return 0;

}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.