Как программно проверить использование памяти достаточно портативным способом? (C / C++)

Я пишу кроссплатформенный код на C++ (Windows, Mac). Есть ли способ проверить, сколько памяти используется текущим процессом? Очень надуманный фрагмент для иллюстрации:

unsigned long m0 = GetMemoryInUse();
char *p = new char[ random_number ];
unsigned long m1 = GetMemoryInUse();
printf( "%d bytes used\n", (m1-m0) );

Конечно, (m1-m0) должно быть равно random_number, но я пытаюсь сделать это на более сложном уровне, включая возможные вызовы библиотеки, которые могут выделить память.

Не рекомендуется следующее:

  1. Используйте Valgrind (или ему подобное)
  2. Используйте настраиваемый распределитель памяти для отслеживания выделенная память.

Проверьте mallinfo ().

An̲̳̳drew 13.03.2009 01:06
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
15
1
5 336
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий
  • Нет портативного способа сделать это.
  • Для большинства операционных систем нет даже надежного способа сделать это для конкретной ОС.

Возможно Вы правы. Я просто надеялся, что что-то упустил. :) Скорее всего, у меня просто будет кастомный менеджер памяти.

Patrick Hogan 16.12.2008 23:34

вы можете использовать шаблон «пул памяти». Все объекты в вашей программе выделяют / освобождают память из этого пула, чтобы вы могли узнать, сколько памяти вы потребляете.

Вот код, который я написал, чтобы попытаться сделать это переносимым способом. Это не идеально, но я думаю, что он должен, по крайней мере, дать указание на то, как это сделать на каждой из нескольких платформ.

(P.S. Я регулярно использую OSX и Linux и знаю, что это хорошо работает. Я использую Windows реже, поэтому оговорки относятся к пункту Windows, но я думаю, что это правильно.)

#ifdef __linux__
# include <sys/sysinfo.h>
#endif

#ifdef __APPLE__
# include <mach/task.h>
# include <mach/mach_init.h>
#endif

#ifdef _WINDOWS
# include <windows.h>
#else
# include <sys/resource.h>
#endif

/// The amount of memory currently being used by this process, in bytes.
/// By default, returns the full virtual arena, but if resident=true,
/// it will report just the resident set in RAM (if supported on that OS).
size_t memory_used (bool resident=false)
{
#if defined(__linux__)
    // Ugh, getrusage doesn't work well on Linux.  Try grabbing info
    // directly from the /proc pseudo-filesystem.  Reading from
    // /proc/self/statm gives info on your own process, as one line of
    // numbers that are: virtual mem program size, resident set size,
    // shared pages, text/code, data/stack, library, dirty pages.  The
    // mem sizes should all be multiplied by the page size.
    size_t size = 0;
    FILE *file = fopen("/proc/self/statm", "r");
    if (file) {
        unsigned long vm = 0;
        fscanf (file, "%ul", &vm);  // Just need the first num: vm size
        fclose (file);
       size = (size_t)vm * getpagesize();
    }
    return size;

#elif defined(__APPLE__)
    // Inspired by:
    // http://miknight.blogspot.com/2005/11/resident-set-size-in-mac-os-x.html
    struct task_basic_info t_info;
    mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
    task_info(current_task(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
    size_t size = (resident ? t_info.resident_size : t_info.virtual_size);
    return size;

#elif defined(_WINDOWS)
    // According to MSDN...
    PROCESS_MEMORY_COUNTERS counters;
    if (GetProcessMemoryInfo (GetCurrentProcess(), &counters, sizeof (counters)))
        return counters.PagefileUsage;
    else return 0;

#else
    // No idea what platform this is
    return 0;   // Punt
#endif
}

У вас есть случайный #endif в строке перед определением #elif (ЯБЛОКО).

Judge Maygarden 16.12.2008 23:30

К сожалению, это не работает. :( Чем больше я копаю, тем больше кажется, что нет хорошего способа сделать это, кроме кастомного менеджера памяти.

Patrick Hogan 16.12.2008 23:32

@pbhogan Я бы придерживался кода, зависящего от платформы, как указано выше. Приведенный выше код немного запутан, но он должен обеспечить вам хороший старт (в части Windows есть ошибка - counters! = Count, см. msdn.microsoft.com/en-us/library/ms683219(VS.85).aspx и связанный пример).

Hrvoje Prgeša 17.12.2008 00:04

@pbhogan Что касается специального диспетчера памяти, который не даст вам размер стека, память, зарезервированную системой, память, выделенную библиотекой, и так далее ... Это новый проект? зачем вам это?

Hrvoje Prgeša 17.12.2008 00:06

определение Windows должно быть _WIN32, _WINDOWS по умолчанию определен только для DLL и GUI EXE, консольные приложения не получают _WINDOWS, так как он не определен заранее; ссылка msdn.com/library/b0084kay

Matthew 07.12.2016 02:37

Я использовал SIGAR API для получения всевозможной информации, связанной с системой, довольно переносимой на основных платформах. Это тоже с открытым исходным кодом (Apache). В этой относительно тривиальной, но утомительной работе действительно нет необходимости изобретать велосипед.

Другие вопросы по теме