簡體   English   中英

c + +未使用的僅包含指針的對象的內存,如何釋放?

[英]c++ unused memory of objects containing only pointers , how to free?

我剛剛編寫了一些處理大型對象的線程代碼。 即使我清理了一個對象的所有內容(不刪除它),它仍然占用GB的RAM。 僅供參考,我在較小的環境中重現了該問題。

此代碼創建一個結構和一個對象,其中包含指向該結構的指針的向量。 然后,我用一些指向結構的指針填充對象(用new創建)。 我想該對象應該只擁有指針的大小,而不是所有指向的結構的大小,但是當我運行代碼時,該對象的大小使用300mb。

當我刪除向量的所有成員然后清理向量時,占用的內存(但現在未使用)仍然很高。 釋放此內存的唯一方法似乎是刪除包含向量的整個對象。 如果向量只是指針向量,為什么向量會保留這么多占用的RAM? 如何釋放它而不必刪除並重新創建對象?

function -> void f_create_heapCleaner_string創建一個字符串,然后將其刪除。 有時,此技巧可以清除堆。

#include <string>
#include <malloc.h>

#include <vector>
#include <iostream>
using namespace std;

struct struct_test_struct {
    string s_internal_data;
};

struct struct_test_struct* BASEDATA_struct_test_struct;

class objhandle_TestStruct__class {
public:
    vector<struct struct_test_struct *> v_pointer_TestStruct;

    unsigned int ui_v_size;

    objhandle_TestStruct__class() {
        ui_v_size = 3000;
    }

    void f_create_heapCleaner_string() {
        string * s_tmp = new string();
        (*s_tmp).assign(1000000, '*');
        (*s_tmp) = "";
        delete s_tmp;
    }

    void f_create_vector(unsigned int ui_size_str) {
        cout << "  f_create_vector() start " << endl;
        malloc_stats();
        for (unsigned int ui = 0; ui < ui_v_size; ui++) {
            struct struct_test_struct * tmp_newstruct = new struct_test_struct();
            (*tmp_newstruct).s_internal_data.assign((ui_size_str + ui), '*');
            v_pointer_TestStruct.push_back(tmp_newstruct);
        }
        cout << "  f_create_vector() end " << endl;
        malloc_stats();
        }

    void f_delete_vector_content() {
            cout << "  f_delete_vector_content() start " << endl;
        malloc_stats();
        for (unsigned int ui = 0; ui < ui_v_size; ui++) {
            delete v_pointer_TestStruct[ui];
        }
        f_create_heapCleaner_string();
        cout << "  f_delete_vector_content() end " << endl;
        malloc_stats();
    }

    void f_clear_vector() {
        cout << "  f_clear_vector() start " << endl;
        malloc_stats();
        v_pointer_TestStruct.clear();
            f_create_heapCleaner_string();
        cout << "  f_clear_vector() end " << endl;
        malloc_stats();
    }

    void f_RUN_FULL_TEST(unsigned int ui_size_str) {
        cout << " .... start test with string size of = " << ui_size_str << endl;
        f_create_vector(ui_size_str);
        f_delete_vector_content();
        f_clear_vector();

    }
};

int main(int argc, char**argv) {
    objhandle_TestStruct__class * ptr_objhandle_TestStruct__class = new         objhandle_TestStruct__class();
    (*ptr_objhandle_TestStruct__class).f_RUN_FULL_TEST(100000);
    (*ptr_objhandle_TestStruct__class).f_RUN_FULL_TEST(10000);
    cout << " DELETE OBJECT start " << endl;
    malloc_stats();
    delete ptr_objhandle_TestStruct__class;
    cout << " DELETE OBJECT finished " << endl;
    malloc_stats();

    return 0;
}

---編譯:g ++ -oa test.cc

然后./a

輸出:

    .... start test with string size of = 100000
  f_create_vector() start
Arena 0:
system bytes     =     135168
in use bytes     =         48
Total (incl. mmap):
system bytes     =     135168
in use bytes     =         48
max mmap regions =          0
max mmap bytes   =          0
  f_create_vector() end
Arena 0:
system bytes     =  309997568
in use bytes     =  309972064
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =  309972064
max mmap regions =          0
max mmap bytes   =          0
  f_delete_vector_content() start
Arena 0:
system bytes     =  309997568
in use bytes     =  309972064
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =  309972064
max mmap regions =          0
max mmap bytes   =          0
  f_delete_vector_content() end
Arena 0:
system bytes     =  309997568
in use bytes     =      32832
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =      32832
max mmap regions =          0
max mmap bytes   =          0
  f_clear_vector() start
Arena 0:
system bytes     =  309997568
in use bytes     =      32832
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =      32832
max mmap regions =          0
max mmap bytes   =          0
  f_clear_vector() end
Arena 0:
system bytes     =  309997568
in use bytes     =      32832
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =      32832
max mmap regions =          0
max mmap bytes   =          0
 .... start test with string size of = 10000
  f_create_vector() start
Arena 0:
system bytes     =  309997568
in use bytes     =      32832
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =      32832
max mmap regions =          0
max mmap bytes   =          0
  f_create_vector() end
Arena 0:
system bytes     =  309997568
in use bytes     =   40094656
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =   40094656
max mmap regions =          0
max mmap bytes   =          0
  f_delete_vector_content() start
Arena 0:
system bytes     =  309997568
in use bytes     =   40094656
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =   40094656
max mmap regions =          0
max mmap bytes   =          0
  f_delete_vector_content() end
Arena 0:
system bytes     =  250077184
in use bytes     =      32832
Total (incl. mmap):
system bytes     =  250077184
in use bytes     =      32832
max mmap regions =          0
max mmap bytes   =          0
  f_clear_vector() start
Arena 0:
system bytes     =  250077184
in use bytes     =      32832
Total (incl. mmap):
system bytes     =  250077184
in use bytes     =      32832
max mmap regions =          0
max mmap bytes   =          0
  f_clear_vector() end
Arena 0:
system bytes     =  250077184
in use bytes     =      32832
Total (incl. mmap):
system bytes     =  250077184
in use bytes     =      32832
max mmap regions =          0
max mmap bytes   =          0
 DELETE OBJECT start
Arena 0:
system bytes     =  250077184
in use bytes     =      32832
Total (incl. mmap):
system bytes     =  250077184
in use bytes     =      32832
max mmap regions =          0
max mmap bytes   =          0
 DELETE OBJECT finished
Arena 0:
system bytes     =     135168
in use bytes     =          0
Total (incl. mmap):
system bytes     =     135168
in use bytes     =          0
max mmap regions =          0
max mmap bytes   =          0

謝謝弗朗切斯科

--------------在對象和結構之間使用和對象容器進行編輯,這將在刪除時釋放內存。struct struct_test_struct {string s_internal_data; };

class objstruct_test_struct_OWNER {
    public:
    vector<struct struct_test_struct *> v_pointer_TestStruct;
};
class objhandle_TestStruct__class {
public:

    class objstruct_test_struct_OWNER * ptr_OBJ;

    unsigned int ui_v_size;

    objhandle_TestStruct__class() {
        ui_v_size = 3000;
    }
.........
    void f_create_vector(unsigned int ui_size_str) {
.....
        ptr_OBJ = new objstruct_test_struct_OWNER();
        cout << "  f_create_vector() start " << endl;
        malloc_stats();
        for (unsigned int ui = 0; ui < ui_v_size; ui++) {
            struct struct_test_struct * tmp_newstruct = new struct_test_struct();
            (*tmp_newstruct).s_internal_data.assign((ui_size_str + ui), '*');
            (*ptr_OBJ).v_pointer_TestStruct.push_back(tmp_newstruct);
        }
.........
    void f_clear_vector() {
.........
  delete ptr_OBJ;
 .........

通過這種方式程序可以工作,這就是輸出

 .... start test with string size of = 100000
  f_create_vector() start
Arena 0:
system bytes     =     135168
in use bytes     =         64
Total (incl. mmap):
system bytes     =     135168
in use bytes     =         64
max mmap regions =          0
max mmap bytes   =          0
  f_create_vector() end
Arena 0:
system bytes     =  309997568
in use bytes     =  309972080
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =  309972080
max mmap regions =          0
max mmap bytes   =          0
  f_delete_vector_content() start
Arena 0:
system bytes     =  309997568
in use bytes     =  309972080
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =  309972080
max mmap regions =          0
max mmap bytes   =          0
  f_delete_vector_content() end
Arena 0:
system bytes     =  309997568
in use bytes     =      32848
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =      32848
max mmap regions =          0
max mmap bytes   =          0
  f_clear_vector() start
Arena 0:
system bytes     =  309997568
in use bytes     =      32848
Total (incl. mmap):
system bytes     =  309997568
in use bytes     =      32848
max mmap regions =          0
max mmap bytes   =          0
  f_clear_vector() end
Arena 0:
system bytes     =     135168
in use bytes     =         32
Total (incl. mmap):
system bytes     =     135168
in use bytes     =         32
max mmap regions =          1
max mmap bytes   =    1007616
 .... start test with string size of = 10000
  f_create_vector() start
Arena 0:
system bytes     =     135168
in use bytes     =         64
Total (incl. mmap):
system bytes     =     135168
in use bytes     =         64
max mmap regions =          1
max mmap bytes   =    1007616
  f_create_vector() end
Arena 0:
system bytes     =   40161280
in use bytes     =   40094816
Total (incl. mmap):
system bytes     =   40161280
in use bytes     =   40094816
max mmap regions =          1
max mmap bytes   =    1007616
  f_delete_vector_content() start
Arena 0:
system bytes     =   40161280
in use bytes     =   40094816
Total (incl. mmap):
system bytes     =   40161280
in use bytes     =   40094816
max mmap regions =          1
max mmap bytes   =    1007616
  f_delete_vector_content() end
Arena 0:
system bytes     =   40161280
in use bytes     =      32848
Total (incl. mmap):
system bytes     =   40161280
in use bytes     =      32848
max mmap regions =          1
max mmap bytes   =    1007616
  f_clear_vector() start
Arena 0:
system bytes     =   40161280
in use bytes     =      32848
Total (incl. mmap):
system bytes     =   40161280
in use bytes     =      32848
max mmap regions =          1
max mmap bytes   =    1007616
  f_clear_vector() end
Arena 0:
system bytes     =    1138688
in use bytes     =         32
Total (incl. mmap):
system bytes     =    1138688
in use bytes     =         32
max mmap regions =          1
max mmap bytes   =    1007616
 DELETE OBJECT start
Arena 0:
system bytes     =    1138688
in use bytes     =         32
Total (incl. mmap):
system bytes     =    1138688
in use bytes     =         32
max mmap regions =          1
max mmap bytes   =    1007616
 DELETE OBJECT finished
Arena 0:
system bytes     =    1138688
in use bytes     =          0
Total (incl. mmap):
system bytes     =    1138688
in use bytes     =          0
max mmap regions =          1
max mmap bytes   =    1007616

我只在這里顯示的問題是,對象似乎一直為自己分配已分配的內存,直到不刪除為止。因此,為設備釋放內存的唯一方法似乎是將數據放入另一個子對象並刪除它。

-------------------最后..我發現,當程序保留一部分內存以供將來使用時,眾所周知,這已被重用。沒關系..我的多線程程序上的問題是malloc創建了這些“ Arenas”,並且在同一時刻在一個大對象malloc中調用了2個malloc時,創建了另一個“ Arena”,為其保留了新的內存映射。程序我最終以沒有免費的ram結束,有4個“ Arenas”映射了超過3gb的ram,但實際上每個映射不到100mb! 因此,問題在於內存映射(無法手動釋放)和線程訪問內存,將未使用的ram乘以這些“ Arenas”,因此在訪問這些對象時我為所有線程創建了一個mutex_lock,因此將它們保留在相同的競技場,沒有“浪費”內存(映射但未使用)進入多個區域。

我希望我已經解釋了我的問題和解決方法..希望這可以對其他人有所幫助;)再次感謝您,弗朗切斯科

-----我仍在測試。.我也看到了這個http://google-perftools.googlecode.com/svn/trunk/doc/tcmalloc.html,他們說的正是我的問題。““在ptmalloc2內存中永遠不能從一個領域移動到另一個領域。這可能會導致大量的空間浪費。”並創建一個不同的內存分配器應該會有所幫助。

如果沒有malloc_stats的源代碼,則很難確切知道您要報告的內容。

但是,要考慮的一件事是,如果您要報告系統頁面,則即使您釋放了C / C ++所使用的內存(使用delete或free),也不會釋放這些頁面。 原因是當您使用new / malloc分配內存時,C運行時庫將請求一段系統內存,然后再細分該內存塊以滿足您的請求。 分配巨大的內存塊時也是如此。 C RTL將分配一個大的系統內存塊,將該內存添加到其可用C RTL內存的已知塊列表中,然后返回指向巨大內存塊的指針。

這里的關鍵是對於大多數標准分配器(不是全部,甚至可能不是您正在使用的分配器),當釋放內存時,該內存不會返回給操作系統,而是保留在可用內存列表中有關將來的新聞和malloc。

因此,如果按照系統頁面顯示可用內存,那么在您免費使用時,該數字不會減少。

看一下Boost的共享指針 嘗試在您的代碼中實現它,這將消除對delete的需要。 基本上,將向量更改為:

vector<boost::shared_ptr<struct struct_test_struct> > v_pointer_TestStruct;

boost::shared_ptr<struct_test_struct> tmp_newstruct( new struct_test_struct() );

...並且您可以完全刪除以下代碼:

    for (unsigned int ui = 0; ui < ui_v_size; ui++) {
        delete v_pointer_TestStruct[ui];
    }

由於調用v_pointer_TestStruct.clear(); 從現在開始將在內部執行此操作。 基本上,這將為您處理所有內存分配(至少針對此結構)。

您需要確保完全了解malloc_stats返回什么。

我要做的最好的就是告訴你這個好職位 下面的代碼段

好吧,顯然,系統字節是為系統保留的字節。 這意味着它們可用於OS和Rung 2及更低版本的庫,但不適用於通常在Prerog Ladder的Rung 4上運行的程序。 不幸的是,使用中的字節是庫中的錯字。 它應該在use_r_個字節中,這表示當前程序的用戶空間(行5和更高版本)中剩余的字節。

執行vector.clear()設置vector.size()== 0,但不能保證與vector.capacity() 換句話說,標准允許std :: vector保持其內存分配,以防萬一您再次用數據填充它。

要使vector釋放其內存,請使用Clear-and-minimize慣用語

vector<struct struct_test_struct *> tmp_empty_vector;
v_pointer_TestStruct.swap(tmp_empty_vector);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM