pthread_create會導致內存泄露

這幾天一直在調試一個系統,系統的功能就是定時發送數據、接收數據然后解析收到的數據,轉換成一定的格式存入數據庫中。我為了并發操作,所以每接收到一個數據包,就調用pthread_create函數創建一個默認屬性的線程進行處理。

?? 系統一開始運行很正常,但是當接收到第299個數據包時,就發生異常,查看程序日志,得知原來自接收到299個數據包后,就不再解析接收到的數據。我本以為是網絡的問題,于是,重啟下程序,結果異常發生在了同樣的位置。這時,我猜想可能是代碼的問題,找到相關代碼,如下:


while?(1)?
{
????len?=?recvfrom(sock,?buf,?MAXPACKETSIZE,?

??????????????????? 0,(struct?sockaddr?*)&c_addr,?&addr_len);
????.......
????targ?=?(struct?threadarg?*)malloc(sizeof(struct?threadarg));
????memset(targ,?0,?sizeof(struct?threadarg));
????????
????targ->len?=?len;
????targ->ip?=?(int)c_addr.sin_addr.s_addr;
????memcpy(targ->buffer,?buf,?len);
????printf("received\n");
????????

????//注:targ在線程中會被free掉。

????pthread_create(&tid,?NULL,?insertToList,?(void?*)targ);
}


從代碼看不出什么異常,由于解析數據是調用pthread_create函數創建一個默認屬性的線程進行處理,如果沒有解析,那么,應該是pthread_create函數沒有創建成功。而pthread_create函數創建失敗最可能的原因應該就是系統資源不足,根據經驗,線程的默認堆棧大小是1MB,就是說,系統每創建一個線程就要至少提供1MB的內存,那么,創建線程失敗,極有可能就是內存不夠用了。從代碼中看不出有內存泄露的現象,有malloc的地方就會有free對應。而仍然出現問題,那么,唯一的解釋就是pthread_create會導致內存泄露! pthread_create創建的線程結束后,系統并未回收其資源,從而導致了泄露。

??? 然后從網上查了相關資料如下:


??? ?線程的分離狀態決定一個線程以什么樣的方式來終止自己。線程的默認屬性是非分離狀態,這種情況下,原有的線程等待創建的線程結束。只有當pthread_join()函數返回時,創建的線程才算終止,才能釋放自己占用的系統資源。而分離線程不是這樣子的,它沒有被其他的線程所等待,自己運行結束了,線程也就終止了,馬上釋放系統資源。程序員應該根據自己的需要,選擇適當的分離狀態。

???? 從上面的描述中可以得知如果調用pthread_create函數創建一個默認非分離狀態的線程,如果不用pthread_join()函數,線程結束時并不算終止,所以仍然會占用系統資源。這里有如下幾種方法解決這個問題:
1.使用pthread_join()函數回收相關內存區域。

pthread_t?tid;
void*?state;

pthread_create(&tid,?NULL,?test,?NULL);
pthread_join(tid,?&state);


2.可以調用 pthread_detach() 函數分離線程。

pthread_t?tid;
pthread_create(&tid,?NULL,?test,?NULL);
pthread_detach(tid);


當然,也可以在 thread function 中調用。


void*?test(void*?arg)
{
????.....
????pthread_detach(pthread_self());
????return?NULL;
}


3.使用線程屬性。


pthread_attr_t?attr;
pthread_t?tid;

pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,?PTHREAD_CREATE_DETACHED);

pthread_create(&tid,?&attr,?test,?NULL);

sleep(3);//等待線程結束

pthread_attr_destroy(&attr);


根據實際需要,任選其一即可。?


ps:最后,我寫了個測試程序,然后用valgrind檢查了一下。
測試程序:

#include?<pthread.h>
#include?<stdio.h>

void*?test()
{
????printf("ok\n");
????return;
}
int?main(int?argc,?char**?argv)
{
????????pthread_t?tid;
????????pthread_create(&tid,?NULL,?test,?NULL);
????//pthread_join(tid, NULL);

????return?1;
}

編譯鏈接:
[root@localhost ~]# gcc -g b.c -o b -lpthread
然后,用valgrind進行內存檢查

[root@localhost ~]# valgrind --tool=memcheck --leak-check=full ./b
==20980== Memcheck, a memory error detector
==20980== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==20980== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==20980== Command: ./b
==20980==?
ok
==20980==?
==20980== HEAP SUMMARY:
==20980==???? in use at exit: 272 bytes in 1 blocks
==20980==?? total heap usage: 1 allocs, 0 frees, 272 bytes allocated
==20980==?
==20980== 272 bytes in 1 blocks are possibly lost in loss record 1 of 1
==20980==??? at 0x4C1F1A0: calloc (vg_replace_malloc.c:418)
==20980==??? by 0x4010422: _dl_allocate_tls (in /lib64/ld-2.7.so)
==20980==???? by 0x4E2AB52: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.7.so)
==20980==??? by 0x40059E: main (b.c:13)
==20980==?
==20980== LEAK SUMMARY:
==20980==??? definitely lost: 0 bytes in 0 blocks
==20980==??? indirectly lost: 0 bytes in 0 blocks
==20980==????? ?possibly lost: 272 bytes in 1 blocks
==20980==??? still reachable: 0 bytes in 0 blocks
==20980==???????? suppressed: 0 bytes in 0 blocks
==20980==?
==20980== For counts of detected and suppressed errors, rerun with: -v
==20980== ERROR SUMMARY:? 1 errors from 1 contexts ?(suppressed: 4 from 4)

確實有內存泄露。
修改測試程序:


#include?<pthread.h>
#include?<stdio.h>

void*?test()
{
????printf("ok\n");
????return;
}
int?main(int?argc,?char**?argv)
{
????????pthread_t?tid;
????????pthread_create(&tid,?NULL,?test,?NULL);
????pthread_join(tid,?NULL);
????return?1;
}

編譯鏈接:
[root@localhost ~]# gcc -g b.c -o b -lpthread
然后,用valgrind進行內存檢查

[root@localhost ~]# valgrind --tool=memcheck --leak-check=full ./b
==21013== Memcheck, a memory error detector
==21013== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==21013== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==21013== Command: ./b
==21013==?
ok
==21013==?
==21013== HEAP SUMMARY:
==21013==???? in use at exit: 0 bytes in 0 blocks
==21013==??? total heap usage: 1 allocs, 1 frees, 272 bytes allocated
==21013==?
==21013== All heap blocks were freed -- no leaks are possible
==21013==?
==21013== For counts of detected and suppressed errors, rerun with: -v
==21013== ERROR SUMMARY:? 0 errors from 0 contexts ?(suppressed: 4 from 4)

問題解決。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383395.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383395.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383395.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux_linux常用工具之make/makefile詳解

make/makefile make/makefile: 項目自動化構建工具 makefile:普通文本文件&#xff0c;記錄了項目的構建流程規則。 make: 一個解釋程序&#xff0c;到當前執行make命令的目錄下尋找makefile文件&#xff0c;并且對makefile 中記錄的項目構建規則進行解釋執行。makefile: 編寫…

Linux_linux常用工具(git,vim ,gcc ,gdb,權限)超詳解

git :項目版本控制工具 項目克隆&#xff1a;git clone項目提交&#xff1a;git add&#xff08;本地倉庫提交&#xff09; git commit -m “bak msg”&#xff08;-m 備注信息&#xff09;同步到服務器&#xff1a;git push origin master&#xff08;提交到主分支&…

T20調試札記

最近在調試T20的內存&#xff0c;使用的指令在此記錄一下 1. pmap指令查看指定進程中的內存分布。該指令需要在busybox中開啟 pmap -x 111 2.應用與so需要執行strip操作&#xff0c;可以減小存儲空間的大小 mips-linux-gnu-strip libsysutils.so 3.nm指令和file指令可以查…

samba 2.2.7a 編譯

今天在君正T20上編譯samba 2.2.7a 遇到了一些問題&#xff0c;特此記錄一下 1.自己寫一個build.sh腳本&#xff0c;方便后續的再次編譯 #!/bin/sh # export CFLAGS"-O2 -muclibc" export CPPFLAGS"-O2 -muclibc" export CXXFLAGS"-O2 -muclibc&qu…

Linux_linux常用工具------進度條程序

緩沖區對文件讀寫的影響&#xff1a;數據并沒有直接寫入文件&#xff0c;而是寫入到緩沖區&#xff08;內存&#xff09;中&#xff0c;等到緩沖區中數據寫滿或者刷新緩沖區的時候&#xff0c;才會將數據真正的寫入文件 fflush&#xff08;stdout&#xff09;刷新。 回車與換行…

Ubuntu下QT的安裝詳細教程

本文轉自&#xff1a;http://blog.chinaunix.net/uid-7945126-id-4987195.html 經測試完美解決 ------------------------------------------------------------- 最近需要在Ubuntu下開發桌面軟件&#xff0c;想起了QT。書上介紹的方法太老了&#xff0c;網上找了一大堆安裝方法…

Linux_linux常用工具---閑雜篇(除了vim, 還有哪些常用的牛逼的編輯器, 并能夠橫向對比編輯器之間的區別和優缺點.)

vim自行查找資料, 自行配置插件. 借鑒別人的 " 顯示相關 “”""""""""""""""""""""""""""""""""&…

ubuntu14.04下安裝qt4.8.6 +qt creator

原創作品&#xff0c;允許轉載&#xff0c;轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://248341.blog.51cto.com/238341/1438867以前安裝時沒太注意&#xff0c;安裝qt后發現在qt creator下無法輸入中文&#xff0c;或者中文無法…

網絡基礎一(協議的概念,網絡應用程序設計模式)

協議的概念 什么是協議&#xff1f; 從應用的角度出發&#xff0c;協議可理解為“規則”&#xff0c;是數據傳輸和數據的解釋的規則。 假設&#xff0c;A、B雙方欲傳輸文件。規定&#xff1a; 第一次&#xff0c;傳輸文件名&#xff0c;接收方接收到文件名&#xff0c;應答OK…

ubuntu修改root密碼

sudo passwd root [sudo] password for you &#xff1a;---> 輸入你的密碼&#xff0c;不會顯示 Enter new UNIX password: --- > 設置root 密碼 Retype new UNIX password: --> 重復

linux 消息隊列機制

現在我們來討論第三種也是最后一種System V IPV工具&#xff1a;消息隊列。在許多方面看來&#xff0c;消息隊列類似于有名管道&#xff0c;但是卻沒有與打開與關閉管道的復雜關聯。然而&#xff0c;使用消息隊列并沒有解決我們使用有名管道所遇到的問題&#xff0c;例如管道上…

堆(概念,數據結構中堆與內存堆區的區別 ,堆的基本操作)

堆的特性&#xff1a; 必須是完全二叉樹 用數組實現 任一結點的值是其子樹所有結點的最大值或最小值 最大值時&#xff0c;稱為“最大堆”&#xff0c;也稱大根堆&#xff1b; 在完全二叉樹中&#xff0c;任何一個子樹的最大值都在這個子樹的根結點。最小值時&#xff0c;稱為…

makefile中的shell調用---注意事項

在之前一次編寫makfile時候&#xff0c;有看到相關的makefile中使用$$來引用變量&#xff0c;而且嘗試后發現$$使用居然和${}有類似的功能。當時也沒具體追究相關的用法&#xff0c;當然剛才所說的都是錯誤的觀念 $$&#xff1a;在makefile中會被替換成一個$。 相關資料是這么描…

網絡基礎2(分層模型,通信過程,以太網,ARP協議格式和具體功能詳解)

分層模型 OSI七層模型 OSI模型 1 物理層&#xff1a;主要定義物理設備標準&#xff0c;如網線的接口類型、光纖的接口類型、各種傳輸介質的傳輸速率等。它的主要作用是傳輸比特流&#xff08;就是由1、0轉化為電流強弱來進行傳輸&#xff0c;到達目的地后再轉化為1、0&#…

為github帳號添加SSH keys

使用git clone命令從github上同步github上的代碼庫時&#xff0c;如果使用SSH鏈接&#xff08;如我自己的beagleOS項目&#xff1a;gitgithub.com:DamonDeng/beagleOS.git&#xff09;&#xff0c;而你的SSH key沒有添加到github帳號設置中&#xff0c;系統會報下面的錯誤&…

網絡基礎3(IP段格式,UDP數據報格式,TCP數據報格式)

IP段格式 IP數據報的首部長度和數據長度都是可變長的&#xff0c;但總是4字節的整數倍。 對于IPv4&#xff0c;4位版本字段是4。4位首部長度的數值是以4字節為單位的&#xff0c;最小值為5&#xff0c;也就是說首部長度最小是4x520字節&#xff0c;也就是不帶任何選項的IP首部…

Linux 開發路線

Linux 開發路線&#xff1a; 使用 linux—〉linxu 系統編程開發---〉驅動開發和分析 linux 內核 開始學 linux 內核:最好有三件寶物:《深入理解 linux 內核》《LINUX內核源代碼情景分析》和源代碼。 《深》是綱,《情》是目。最后深入代碼 Linux 內核原理&#xff1a;比較淺顯…

堆的應用(堆排序,TopK問題)

堆的應用 1&#xff09;排序 堆排序 選擇排序 既可以找到最大的放在最后 也可以找到最小的方最前 但是&#xff0c;堆排序不能找最小的放在最前 因為把最小數放在最前&#xff0c;會破壞掉堆的原來的順序&#xff0c;除非重新建堆 1&#xff0c; 2&#xff0c;9&#xff0c…

有名管道和無名管道的區別

1&#xff09;無名管道:管道是半雙工的&#xff0c;數據只能向一個方向流動&#xff1b;需要雙方通信時&#xff0c;需要建立起兩個管道&#xff1b;只能用于父子進程或者兄弟進程之間&#xff08;具有親緣關系的進程&#xff09;。 單獨構成一種獨立的文件系統&#xff1a;管道…

網絡基礎4(TCP三次握手,四次握手,TCP流量控制,TCP狀態轉換 , TCP異常斷開,設置TCP屬性,端口復用)

TCP協議 TCP通信時序 下圖是一次TCP通訊的時序圖。TCP連接建立斷開。包含大家熟知的三次握手和四次握手。 TCP通訊時序 在這個例子中&#xff0c;首先客戶端主動發起連接、發送請求&#xff0c;然后服務器端響應請求&#xff0c;然后客戶端主動關閉連接。 兩條豎線表示通訊的…