我的对象消耗了多少内存

时间:2011-11-11 12:53:26

标签: c++

我想知道以编程方式获取用户定义的类消耗的内存。 以下是该类的声明

struct TrieNode {
    typedef std::map<char, TrieNode *> ChildType;
    std::string    m_word;
    bool      m_visited;
}

我已将264061个字词插入此Trie。在此之后我执行sizeof(trieobject)时,它只会显示32。我怎么知道这些数据结构使用了多少确切的内存。

5 个答案:

答案 0 :(得分:4)

我用

valgrind --tool=massif ./myprogram -opt arg1 arg2
ms_print massif.* | less -SR

为此。来自this page

的示例输出
19.63^                                               ###                      
     |                                               #                        
     |                                               #  ::                    
     |                                               #  : :::                 
     |                                      :::::::::#  : :  ::               
     |                                      :        #  : :  : ::             
     |                                      :        #  : :  : : :::          
     |                                      :        #  : :  : : :  ::        
     |                            :::::::::::        #  : :  : : :  : :::     
     |                            :         :        #  : :  : : :  : :  ::   
     |                        :::::         :        #  : :  : : :  : :  : :: 
     |                     @@@:   :         :        #  : :  : : :  : :  : : @
     |                   ::@  :   :         :        #  : :  : : :  : :  : : @
     |                :::: @  :   :         :        #  : :  : : :  : :  : : @
     |              :::  : @  :   :         :        #  : :  : : :  : :  : : @
     |            ::: :  : @  :   :         :        #  : :  : : :  : :  : : @
     |         :::: : :  : @  :   :         :        #  : :  : : :  : :  : : @
     |       :::  : : :  : @  :   :         :        #  : :  : : :  : :  : : @
     |    :::: :  : : :  : @  :   :         :        #  : :  : : :  : :  : : @
     |  :::  : :  : : :  : @  :   :         :        #  : :  : : :  : :  : : @
   0 +----------------------------------------------------------------------->KB     0                                                                   29.48

Number of snapshots: 25
 Detailed snapshots: [9, 14 (peak), 24]

日志的其余部分详细说明了内存分配的最高百分比,您可以具体地看到什么类型的类占用堆内存的百分比(以及分配来自调用堆栈的位置),例如:

--------------------------------------------------------------------------------
  n        time(B)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 10         10,080           10,080           10,000            80            0
 11         12,088           12,088           12,000            88            0
 12         16,096           16,096           16,000            96            0
 13         20,104           20,104           20,000           104            0
 14         20,104           20,104           20,000           104            0

99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->49.74% (10,000B) 0x804841A: main (example.c:20)
| 
->39.79% (8,000B) 0x80483C2: g (example.c:5)
| ->19.90% (4,000B) 0x80483E2: f (example.c:11)
| | ->19.90% (4,000B) 0x8048431: main (example.c:23)
| |   
| ->19.90% (4,000B) 0x8048436: main (example.c:25)
|   
->09.95% (2,000B) 0x80483DA: f (example.c:10)
  ->09.95% (2,000B) 0x8048431: main (example.c:23)

答案 1 :(得分:1)

嗯,这不是那么容易做到的。首先,m_word是一个可变大小的字符串吗?在内部,std :: string包含一系列字符。这同样代表std :: map。我想你可以根据地图* TrieNode的大小得到一个粗略的估计,但这只是一个粗略的估计。

我认为使用外部工具进行一些代码分析会更有帮助。如果你没有任何工具,你甚至可以使用任务管理器:)。

答案 2 :(得分:0)

你的“对象大小”是sizeof(std :: string)+ sizeof(bool)+ m_word.capacity()+ padding bytes或sizeof(trieobject)+ m_word.capacity()

答案 3 :(得分:0)

这是我提出的一段GCC代码,你可以在一个测试程序中使用它,你只需要实例化你的类的一个对象并用它做一些典型的工作。该代码取代了全局operator new()operator delete();所以它只会跟踪::new表达式和标准分配器的分配,只要标准分配器本身使用::operator new()(GCC就是这种情况)。

由于我们需要跟踪指针及其分配,我们需要一个单独的映射,当然不能使用标准分配器本身;海湾合作委员会的malloc-allocator正在拯救。

我们使用静态初始化的全局来使内存跟踪器在main返回后打印其数据。

#include <unordered_map>
#include <string>
#include <iostream>
#include <ext/malloc_allocator.h>

struct Memtrack
{
  typedef std::unordered_map<void*, std::size_t, std::hash<void*>,
     std::equal_to<void*>, __gnu_cxx::malloc_allocator<void*>> AllocMap;

  static int memtrack;
  static int memmax;
  static AllocMap allocs;

  Memtrack() { std::cout << "starting tracker: cur = " << memtrack  << ", max = " << memmax << ".\n"; }
  ~Memtrack() { std::cout << "ending tracker: cur = " << memtrack  << ", max = " << memmax << ".\n"; }

  static void track_new(std::size_t n, void * p)
  {
    memtrack += n;
    if (memmax < memtrack) memmax = memtrack;
    allocs[p] = n;

    std::cout << "... allocating " << n << " bytes...\n";
  }
  static void track_delete(void * p)
  {
    const int n = int(allocs[p]);
    memtrack -= n;
    std::cout << "... freeing " << n << " bytes...\n";
  }

} m;

int Memtrack::memtrack = 0;
int Memtrack::memmax = 0;
Memtrack::AllocMap Memtrack::allocs;

void * operator new(std::size_t n) throw(std::bad_alloc)
{
  void * const p = std::malloc(n);
  Memtrack::track_new(n, p);
  return p;
}
void operator delete(void * p) throw()
{
  Memtrack::track_delete(p);
  std::free(p);
}

int main()
{
  std::cout << "Beginning of main.\n";

  std::unordered_map<std::string, int> m;  // this piece of code
  m["hello"] = 4;                          // is a typical test for working
  m["world"] = 7;                          // with dynamic allocations

  std::cout << "End of main.\n";
}

一些典型的输出:

starting tracker: cur = 0, max = 0.
Beginning of main.
... allocating 48 bytes...
... allocating 12 bytes...
... allocating 12 bytes...
End of main.
... freeing 12 bytes...
... freeing 12 bytes...
... freeing 48 bytes...
ending tracker: cur = 0, max = 72.

答案 4 :(得分:-1)

微不足道的。 如果你有一些时间(可能是这种情况,如果你只对调试/优化目的的大小感兴趣)。这种方法可能不适合生产代码!

#include <malloc.h>

template <typename T> int objSize(T const* obj) {
  // instead of uordblks, you may be interested in 'arena', you decide!
  int oldSize = mallinfo().uordblks;
  T* dummy = new T(*obj);
  int newSize = mallinfo().uordblks;
  delete dummy;
  return newSize - oldSize;
}