Подтвердить что ты не робот

Отслеживать выделение памяти С++

Я ищу способ отслеживать выделения памяти в программе на С++. Меня не интересуют утечки памяти, которые, похоже, пытаются найти большинство инструментов, а скорее создают профиль использования памяти для приложения. Идеальный вывод будет либо большим списком имен функций, либо числом максимальных выделенных байтов со временем или лучше, графическим представлением кучи во времени. Горизонтальная ось - это время, пустое пространство вертикальной оси. Каждая функция получит собственный цвет и рисует линии в соответствии с выделенными байтами кучи. Бонусные точки для идентификации выделенных типов объектов.

Идея состоит в том, чтобы найти узкие места памяти/визуализировать, какие функции/потоки потребляют большую часть памяти, и должны быть нацелены на дальнейшую оптимизацию.

Я кратко посмотрел на Purify, BoundsChecker и AQTime, но они, похоже, не так, как я. Valgrind выглядит подходящим, однако я на Windows. Memtrack выглядит многообещающим, но требует значительных изменений в исходном коде.

Мои навыки Google должны были подвести меня, потому что это не похоже на такой необычный запрос? Вся необходимая информация для создания такого инструмента должна быть легко доступна из программных отладочных символов плюс вызовы API runtime - no?

4b9b3361

Ответ 1

Мониторинг использования памяти ПК для разработки игр содержит почти идеальный пример того, что я искал. Это заняло некоторое время, чтобы запустить его, но автор статьи очень помог. Здесь вы можете найти исходный код инструмента Memtracer.

У меня также появилось много полезных ответов на SWENG (список рассылки Software Engineering). Этот поток называется "[Sweng-Gamedev], контролирующим использование памяти С++?".

Ответ 2

Используйте Valgrind и его инструмент Massif. Его пример вывода (его часть):

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)

Итак, вы получите подробную информацию:

  • ВОЗ выделила память (функции: g(), f() и main() в приведенном выше примере); вы также получаете полную обратную трассировку, ведущую к распределению функции,
  • для структуры данных WHICH, в которую поступила память (в приведенном выше примере нет структур данных),
  • КОГДА это произошло,
  • какой PERCENTAGE для всей выделенной памяти (g: 39,7%, f: 9,95%, основная: 49,7%).

Вот Руководство для массива

Вы можете отслеживать распределение кучи, а также распределение стека (по умолчанию отключено).

PS. Я просто прочитал, что вы в Windows. Я оставлю ответ, потому что он дает представление о том, что вы можете получить из возможного инструмента.

Ответ 3

Microsoft имеет хорошо документированные функции отслеживания памяти. Однако по какой-то причине они не очень известны в сообществе разработчиков. Это функции отладки ЭЛТ. Хорошей отправной точкой будут функции CRT Debug Heap.

Проверьте следующие ссылки для более подробной информации

  1. Функции отчетов о состоянии кучи
  2. Отслеживание запросов на выделение кучи. Вероятно, это та функциональность, которую вы ищете.

Ответ 4

Для общего трекера памяти С++ вам необходимо перегрузить следующее:

global operator new
global operator new []
global operator delete
global operator delete []
any class allocators
any in-place allocators

Сложный бит получает полезную информацию, перегруженные операторы имеют только информацию о размерах для распределителей и указатели памяти для удаления. Один из ответов - использовать макросы. Я знаю. Насти. Пример - место в заголовке, которое включено из всех исходных файлов:

#undef new

void *operator new (size_t size, char *file, int line, char *function);
// other operators

#define new new (__FILE__, __LINE__, __FUNCTION__)

и создайте исходный файл с помощью:

void *operator new (size_t size, char *file, int line, char *function)
{
  // add tracking code here...
  return malloc (size);
}

Вышеуказанное работает только в том случае, если у вас нет оператора, определенного в классе. Если у вас есть некоторые в области класса, выполните следующие действия:

#define NEW new (__FILE__, __LINE__, __FUNCTION__)

и замените "новый тип" на "НОВЫЙ тип", но это требует изменения большого количества кода.

Как макрос, удаление трекера памяти довольно просто, заголовок становится:

#if defined ENABLED_MEMORY_TRACKER
#undef new

void *operator new (size_t size, char *file, int line, char *function);
// other operators

#define NEW new (__FILE__, __LINE__, __FUNCTION__)
#else
#define NEW new
#endif

и файл реализации:

#if defined ENABLED_MEMORY_TRACKER
void *operator new (size_t size, char *file, int line, char *function)
{
  // add tracking code here...
  return malloc (size);
}
endif

Ответ 6

В Mac OS X вы можете использовать инструмент профилирования кода Shark для этого, IIRC.

Ответ 7

В Xcode вы можете использовать Инструменты для отслеживания распределений, использования виртуальной машины и нескольких других параметров. В основном популярны среди разработчиков iOS, но стоит попробовать.

Ответ 8

"Графическое представление кучи во времени" - близко к тому, что вы ищете, реализовано в Intel (R) Single Event API, подробности можно найти в этой статье (ее довольно большой, чтобы добавить ее здесь). Распределение блоков памяти со временем

Показывает временную шкалу распределений по размеру блока и позволяет добавить дополнительную метку к вашему коду, чтобы лучше понять всю картину.

Ответ 9

В Visual Studio IDE имеется встроенная поддержка профилирования кучи (с 2015 года), которую, пожалуй, проще всего начать. Он имеет графическое представление использования кучи с течением времени и может отслеживать распределение по функции/методу.

heap profiling

CRT также имеет поддержку отладки и профилей, которая является более подробной и более низкоуровневой. Вы можете отслеживать данные и отображать результаты, используя другой инструмент:

В частности, посмотрите на _CrtMemCheckpoint и связанные с ним функции.