2016-09-22 52 views
1

我們有一個程序在長時間運行後由於內存不足而導致4Gb崩潰。該項目使用C++,openSuse11,12,包括鏈接到各種共享內存和其他庫。C++,是否泄漏?可以做些什麼

從PID的pmap監視堆增加和總內存增加,它們完全類似。這意味着該過程以2.5Gb和堆〜0開始,並在崩潰之前Total = 4 Gbheap = 1.5 Gb

我們用valgrind做了一些運行,結果令人費解。您可以在下面看到運行20分鐘的摘要。

==30042== HEAP SUMMARY: 
==30042==  in use at exit: 706,413 bytes in 3,345 blocks 
==30042== total heap usage: 1,770,240 allocs, 1,766,895 frees, 173,813,303 bytes allocated 

==30042== LEAK SUMMARY: 
==30042== definitely lost: 96 bytes in 3 blocks 
==30042== indirectly lost: 27 bytes in 3 blocks 
==30042==  possibly lost: 344 bytes in 2 blocks 
==30042== still reachable: 705,946 bytes in 3,337 blocks 
==30042==      of which reachable via heuristic: 
==30042==       stdstring   : 62 bytes in 2 blocks 
==30042==   suppressed: 0 bytes in 0 blocks 

監測PMAP,我們知道,內存總量增加了130 Mb但相較於Valgrind的報告中,我們可以看到有泄漏,但沒有真正貼近130 Mb

我們的問題:

  • 有人可以幫助我瞭解Valgrind的總結,以及它如何涉及到130 Mb失去了什麼?

  • 這是泄漏與否?

  • valgrind報告 裏面共享的內存是怎麼回事?
  • 即使SM中有泄漏,難道它 還在堆中嗎?他們的大小在合理的水平。
  • 我已經閱讀過各種資料,即使釋放內存與delete[] or free()系統仍然可能保留未來 使用的空間。如果是這樣的話,可以做些什麼?

*編輯這個堆的使用似乎是無限制的地方是,當該程序是一個服務器,使一個DB調用(固體SQL)連續大量的數據,其中分配了大量的空間。它不在共享內存中。我們看到釋放管理得當,可以做些什麼?

+1

關於'free'的使用:當你使用malloc對象時,如果需要的話,你的程序向OS請求更多的內存頁面。你一直在閱讀的是'free'不會將這些頁面釋放回操作系統,而是讓它們保持在一起。這意味着當你再次請求更多內存時,程序不需要向操作系統請求更多頁面:它已經有了這些頁面。你的程序將覆蓋free'd內存中的舊數據,所以這不是實際的泄漏。 – CoconutBandit

+0

它大部分是可到達的,這意味着指向它的變量不超出範圍或不被破壞。這意味着它可以合法使用內存。 – imreal

+0

你在32位的環境? – imreal

回答

1

查看Valgrind套件中的Massif工具。堆分析器將幫助您瞭解程序如何繼續增長而不受限制。無限增長似乎是問題而不是泄漏。

有人可以幫助我瞭解Valgrind的總結,以及它如何 涉及到130 MB失去了什麼?

Valgrind表示程序使用了170mb的堆,它不會離你的號碼太遠。較長的運行時間可能會顯示最大堆大小不斷增加。

這是泄漏與否?

該報告沒有顯示很多泄漏的方式。看起來程序清理得很好。峯值堆的使用似乎是問題。

valgrind報告共享內存中發生了什麼?

不,Valgrind看着堆內存是進程本地。

即使SM中有泄漏,難道它仍然在 堆中呢?他們的大小在合理的水平。

不,共享內存不是堆內存。 ipcs和其他工具可以顯示正在使用的共享內存的數量。 32位進程的總可尋址空間爲4GB,因此映射到進程的共享內存量可以減少可用堆空間的數量。

我已閱讀各種來源,與 釋放內存,即使刪除[]或free()系統仍然可以保持對 將來使用而保留的空間。如果是這樣的話,可以做些什麼?

是的,這是正確的。一旦將內存分配給進程,它將不會返回到操作系統,直到進程退出。堆將在一個進程中重複使用,所以堆的最大大小不會增加,除非實際使用。沒有什麼可以在用戶層面完成,通常這不是問題。

重申,程序中的數據結構可能無限制地增長。例如,正在無休止地添加到的鏈接列表。由於數據仍然可以訪問,這在技術上並不是泄漏,並且不會顯示在valgrind報告中。堆分析器(如Massif)可以指向源代碼中分配大量堆內存的區域。

+0

感謝您的回答! 該程序是一個服務器應用程序,它必須始終處於開啓狀態,應如何應對您提到的無限增長?由於它似乎清理得很好,除了重新啓動應用程序之外,還有人可以做些什麼? – thahgr

+0

請看看編輯,如果有幫助 – thahgr

+1

只有3個選項。 1)在內存耗盡之前重新啓動進程。 2)切換到64位模型,這樣過程可以繼續增長。 3)更好地理解內存使用情況並將未使用的內存釋放回堆中。 3)是最好的,但也可能是最難的。 1)很簡單,可能是在生產環境中最直接有用的。 –