標籤:

c++的std::string內存泄漏?

#include &
#include & #include &
#include &

using namespace std;
using namespace std::chrono_literals;

int main() {
for (int i = 0; i &< 20; i++) { thread([] { string temp; for (int j = 0; j &< 2000000; j++) { temp += "haha"; } }).join(); } cout &<&< "all done" &<&< endl; this_thread::sleep_for(200s); return 0; }

像上面這段代碼, 用g++ 5.4.0編譯後在ubuntu 16.04 下運行.

在輸出all done之後用pmap查看進程仍然佔用近30M的內存, 然而不用線程, 換用普通的函數調用則只有幾百K的佔用, 這是什麼現象??

#include &
#include & #include &
#include &

using namespace std;
using namespace std::chrono_literals;

int main() {
for (int i = 0; i &< 20; i++) { ([] { string temp; for (int j = 0; j &< 2000000; j++) { temp += "haha"; } })(); } cout &<&< "all done" &<&< endl; this_thread::sleep_for(200s); return 0; }


先搞清楚什麼叫內存泄漏吧。

內存泄漏的意思是,一塊申請來的內存,沒有人管了。而這裡,每一個申請的內存都有std::string好好的管著,所以不管出什麼狀況都不是內存泄漏,只是釋放時機跟你預期不同。


不同的malloc實現是可以有不同的優化的。即便free了也可以自己維護空閑內存池,不一定要還給OS。

而gcc的ptmalloc以前老的版本在釋放內存的時候會把空閑塊合併然後如果可以縮減堆頂的話就儘可能地把堆頂內存還給操作系統,不能縮減堆頂的話就自己留著,下次分配內存的時候再復用。現在的版本不清楚還是不是這麼實現了,但是應該也差不多的。

為了性能和減少鎖全局堆管理器,現在大多數malloc實現都會加線程緩存。

所以,如果只有一個線程的話,線程緩存回收後就很容易合併之後還給全局堆管理器,然後還給操作系統。而多線程以後,那些線程緩存可能還會暫時留著不還給操作系統,這樣如果你後面又開新線程了就可以直接用,不需要再去全局堆分配一個。所以也更可能最終沒被合併然後還給OS。

這種情況並不是內存泄露,如果你要排查內存泄露,還是以valgrind --tool=memcheck或者其他類似的工具為準。


通過pmap不能證明泄漏。進程的heap內存是通過brk來實現的,釋放的時候,不會立刻還給系統的。


並沒有泄露

單線程時候實際上每次string的對象都被分配了同一塊內存復用。

多線程的時候顯然不會復用,每個線程都有自己的string對象。

至於為什麼跑出來之後內存還沒釋放,這是Linux內存管理的策略造成的。釋放不是立刻進行的,系統會為你保留一段時間,以免你再次申請。


明顯是多線程那邊的事啊,你這從頭到尾都沒在堆上new什麼新的東西出來哪來的內存泄露

不信你直接valgrind一下你的程序就知道了


這應該和內存泄漏沒啥關係,內存主要消耗在開闢線程上。linux默認一個線程保留8M棧空間,20個線程再加其他雜七雜八的東西,30M不奇怪。


The Linux Programming Interface 7.1.2節

Allocating Memory on the Heap: malloc() and free()

In general, C programs use the malloc family of functions to allocate and deallocate

memory on the heap. These functions offer several advantages over brk() and

sbrk(). In particular, they:

are standardized as part of the C language;

are easier to use in threaded programs;

provide a simple interface that allows memory to be allocated in smallunits; and

allow us to arbitrarily deallocate blocks of memory, which are maintained on a

free list and recycled in future calls to allocate memory.

The malloc() function allocates size bytes from the heap and returns


貸個房貸,除了月供之外提前還貸也是有各種限制的…手頭上有了100塊就去提前還貸,人工費就多少,銀行還嫌煩呢。


用 vs2015 試了一下,for循環內最多佔用過11M,但是退出for循環之後就立刻變為0了,沒有泄露呀,不曉得g++是什麼情況


我覺得這不是用C++的人該考慮的問題,這就好比你開著車,總擔心車輪子會掉下來一樣。


推薦閱讀:

TAG:Linux | C | 線程 | g |