2011-07-15 26 views
5

我一直在試圖追蹤內存問題幾天 - 我的程序使用大約3GB的內存,當它應該使用大約200MB-300MB。 Valgrind實際上報告說,它在峯值時使用了〜300MB,並且沒有報告任何內存泄漏。無法追蹤大量內存使用情況

該程序讀取輸入文件,並將每個唯一字存儲在該文件中。它是多線程的,我一直在使用4個線程運行它。我的數據的主要來源是:爲wchar_t的

  • 恆定大小的陣列(4MB總)
  • 字和相關聯的值的列表之間的映射。這隨着輸入的大小而增長。如果輸入文件中有1,000,000個唯一字,則樹中將有1,000,000個條目。

我正在做大量的分配和釋放(使用新的和刪除) - 每個唯一的單詞至少兩個。是否有可能因爲某種原因,我自由的記憶沒有被重用,導致程序不斷獲取越來越多的記憶?隨着它繼續運行,它始終抓住更多。

一般來說,關於我應該從哪裏出發的任何想法?

編輯1(根據格雷厄姆的建議): 我會嘗試的一條路徑是最小化分配。我將使用每個線程的單個字符串(如果一個單詞比這個字符串長,偶爾會增長),但如果我正確記住我的代碼,這將消除大量的新/刪除調用。如果一切順利,我會留下:一次分配輸入緩衝區,一次分配字符串每線程(有一些reallocs),兩個分配每個地圖項(一個用於鍵,一個用於值)。

謝謝!

+0

格雷厄姆的回答似乎有效。你如何確定正在使用多少內存以及你正在運行什麼操作系統(64位或32位)?你正在新建/刪除的對象是數據結構還是完整的類對象? – Foon

+0

我使用Valgrind和命令免費-m(報告有多少內存是免費的,當它使用大量內存時給我一個粗略的想法)。這是在64位Linux上。我已經試過使用std :: wstring和c風格的字符串。 – lapis

回答

7

這很可能是堆碎片。由於您正在分配和釋放如此龐大數量的小塊,因此可能會有大量小塊空閒塊,這些小塊空間太小而不能被後續分配重用。由於這些塊實際上被浪費了,該過程必須不斷從系統中獲取越來越多的內存來兌現新的分配。

您可能能夠通過首先在string::reserve()的每個字符串中預留足夠大的默認容量,然後在清除字符串時清空字符串(而不是刪除)來緩解這種影響。然後,保留空字符串的列表,以便重複使用,而不是始終分配新字符串。

編輯:上述建議假定被分配的對象是std::string s。如果他們不是,那麼你可能仍然可以應用保留舊空物體的一般技術來重用。

+0

這聽起來像是最可能出現的問題,感謝您的輸入!編輯我的原始帖子,我會嘗試一個策略。 – lapis

0

你的程序釋放的內存應該返回到它可以再次分配的堆。

但是,這並不意味着它被釋放回操作系統。通常,應用程序將繼續「擁有」已分配和釋放的內存。

這是一個Windows的應用程序?你如何分配和釋放內存?你如何確定應用程序使用了多少內存?

+0

如果他使用Valgrind,那麼它是Linux。 –

+0

是的它是使用gcc 4.4.4在Linux中構建的,我使用new/delete,使用valgrind進行分析並使用-m – lapis

0

如果可以,您應該嘗試將資源分配包裝到類中。在構造函數中調用new,並在析構函數中刪除。嘗試並利用範圍,以便更自動地完成內存管理。

http://en.wikipedia.org/wiki/RAII