Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我的对象消耗了多少内存_C++ - Fatal编程技术网

C++ 我的对象消耗了多少内存

C++ 我的对象消耗了多少内存,c++,C++,我想知道如何通过编程方式获取我的用户定义类所消耗的内存。 下面是该类的声明 struct TrieNode { typedef std::map<char, TrieNode *> ChildType; std::string m_word; bool m_visited; } 结构三节点{ typedef std::映射子类型; std::字符串m_字; 布尔穆到访; } 我在这个Trie中插入了大约264061个单词。之后,当我执行si

我想知道如何通过编程方式获取我的用户定义类所消耗的内存。 下面是该类的声明

struct TrieNode {
    typedef std::map<char, TrieNode *> ChildType;
    std::string    m_word;
    bool      m_visited;
}
结构三节点{ typedef std::映射子类型; std::字符串m_字; 布尔穆到访; }
我在这个
Trie
中插入了大约264061个单词。之后,当我执行
sizeof(trieobject)
时,它只显示
32
。我如何知道这些数据结构使用了多少精确内存。

好吧,这并不容易做到。首先,m_单词是一个大小可变的字符串,对吗?在内部,std::string包含一个字符数组。这同样代表std::map。我想你可以根据地图的大小得到一个粗略的估计,但这只是一个粗略的估计

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

我使用

valgrind --tool=massif ./myprogram -opt arg1 arg2
ms_print massif.* | less -SR
为此。来自的样本输出

日志的其余部分详细说明了内存分配的最高百分位数,您可以具体看到什么类型的类占用了多少%的堆内存(以及根据调用堆栈分配的起始位置),例如:


琐碎的如果您有时间(如果您只是出于调试/优化目的而对大小感兴趣,则可能是这样)。这种方法可能不适合生产代码

#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;
}
#包括
模板int对象大小(T常量*obj){
//你可以选择“竞技场”,而不是uordblks!
int oldSize=mallinfo().uordblks;
T*虚拟=新的T(*obj);
int newSize=mallinfo().uordblks;
删除虚拟;
返回newSize-oldSize;
}

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

下面是我为GCC编写的一段代码,您可以在测试程序中使用它,在测试程序中只实例化类的一个对象并使用它进行一些典型的工作。该代码替换全局
运算符new()
运算符delete()
;因此,只要标准分配器本身使用
::operator new()
(GCC就是这种情况),它将只通过
:new
表达式和标准分配器跟踪分配

由于我们需要跟踪指针及其分配,因此我们需要一个单独的映射,这当然不能使用标准分配器本身;GCC的malloc分配器来帮助解决这个问题

我们使用一个静态初始化的全局函数,使内存跟踪器在
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";
}

您必须跟踪动态分配。如果您只是装配了一个简单的测试程序,那么可以使用
valgrind
来报告堆的使用情况。否则,您将需要修改分配器以使其打印出统计数据。Constantinius是一棵树,可能单词在子元素的子元素中。这是实际代码吗?代码中的
triode
不包含任何子节点,它只定义子节点的类型,并且有两个类型成员:
std::string
bool
sizeof(std::string)+sizeof(bool)+m_word.capacity()+padding bytes或sizeof(triebobject)+m_word.capacity()
mallinfo
不是标准,
是一个C头,
new
不需要在下面使用
malloc()
来进行实际的内存分配。@Karl Knechtel:我找不到OP在哪里陈述了您在评论中暗示的要求。但是,对于你的观点:如果<代码> Malc.H./Cuth>是C标题,那么C++中包含C头文件并不少见。更重要的是:
malloc
不够,因为您必须调用复制构造函数(这就是为什么我需要
new
),所以它将复制
T
的成员。事实上,如果
malloc
足够的话,你会事先知道所需的大小,这会使整个练习毫无意义,不是吗?
#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;
}
#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.