Есть ли способ распечатать объем кучи памяти, выделенной объектом?

Как в работающей программе отслеживать / распечатывать объем кучи памяти, выделенной объектом?

Например:

#include <iostream>
#include <vector>

int main(){

  std::vector<int> v;

  std::cout << heap_sizeof(v) << '\n';

  for (int i = 0; i < 1000; ++i){
    v.push_back(0);
  }

  std::cout << heap_sizeof(v) << '\n';
}

Есть ли реализация, которая могла бы заменить heap_sizeof()?


person Trevor Hickey    schedule 07.07.2016    source источник
comment
В общем случае только для конкретных платформ. Это очень сильно привязано к реализации кучи.   -  person Dark Falcon    schedule 07.07.2016
comment
Кому следует засчитывать shared_ptr ‹›?   -  person lorro    schedule 07.07.2016
comment
вектор, возможно, был не лучшим примером. Я искал что-то, что могло бы работать с нестандартными типами.   -  person Trevor Hickey    schedule 07.07.2016
comment
@TrevorHickey, см. Здесь: stackoverflow.com/questions/949422/   -  person GreatAndPowerfulOz    schedule 07.07.2016


Ответы (3)


Нет, это невозможно, поскольку все в том виде, в каком оно разработано из коробки. Однако у вас есть несколько вариантов сделать это самостоятельно.

Если вам это нужно исключительно для стандартных контейнеров, вы можете реализовать распределитель, который отслеживает память, которая была выделена (а не освобождена) через этот распределитель.

Если вам нужна эта возможность для всего, что выделено через new (независимо от того, контейнер или нет), вы можете предоставить свою собственную реализацию operator new на глобальной и / или зависящей от класса основе и заставить ее (например) построить неупорядоченную карту от указателей на размеры блока, чтобы сообщить вам размер любого выделенного блока (и с этим вам нужно будет предоставить функцию для получения этого размера). В зависимости от платформы это также может быть реализовано с использованием специфичных для платформы функций. Например, когда вы создаете компилятор Microsoft (ну, на самом деле, библиотеку), ваша реализация operator new вообще не должна делать ничего особенного, а функция для получения размера блока будет выглядеть примерно так:

size_t block_size(void const *block) { 
    return _msize(block);
}

Еще одна возможность - увеличить размер выделения каждого запрошенного блока на размер целого числа, достаточно большого, чтобы удерживать этот размер. В этом случае вы должны выделить больший фрагмент данных, чем запрашивал пользователь, и сохранить размер этого блока в начале возвращаемого блока. Когда пользователь запрашивает размер блока, вы берете правильное (отрицательное) смещение от указателя, который он передает, и возвращаете значение, которое вы там сохранили.

person Jerry Coffin    schedule 07.07.2016

Во-первых, v выделяется в стеке, а не в куче.

Чтобы получить общий объем используемого пространства, я предлагаю использовать эту функцию: (Найдено в этой статье и немного изменены)

template <typename T>
size_t areaof (const vector<T>& x)
{
   return sizeof (vector<T>) + x.capacity () * sizeof (T);
} 

Если вы не хотите считать размер самого объекта std::vector, удалите часть с помощью sizeof:

template <typename T>
size_t heap_sizeof (const vector<T>& x)
{
   return x.capacity () * sizeof (T);
} 
person Mattia F.    schedule 07.07.2016
comment
v может быть в стеке, но его содержимое находится в куче. - person GreatAndPowerfulOz; 07.07.2016
comment
Да, конечно. Я просто хотел указать, что v находится в стеке (в его примере). - person Mattia F.; 07.07.2016
comment
В порядке. Попался. Уточнено. - person GreatAndPowerfulOz; 07.07.2016
comment
И, возможно, нет ни стопок, ни куч. C ++ оставляет ваши варианты открытыми. - person user4581301; 08.07.2016
comment
да. Опубликованная мною функция специфична для его примера. - person Mattia F.; 08.07.2016

Если вас не беспокоит учет того, что выделяет каждый объект, и вас больше беспокоит, сколько памяти было выделено / освобождено между определенным моментом времени, вы можете использовать статистические функции malloc. У каждого malloc есть своя версия. В Linux вы можете использовать mallocinfo().

person doron    schedule 07.07.2016