繁体   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