Сколько памяти занимает программа c
Я не очень знаком с указателями, так как я в основном использую Java, а у Java нет указателей, и сейчас я изучаю C ++. В учебнике по C ++, чтобы узнать размер памяти, занимаемой переменной, он использовал размер указателя на переменную, т.е.
Это сбило меня с толку, потому что на первом курсе меня учили программированию на C, что мне нужно будет делать sizeof для самой переменной. Итак, я сначала пришел к выводу, что они имели в виду то же самое. Но когда я попробовал на своем компьютере, у меня были другие результаты. У меня есть следующий код …
Когда я запускаю приведенный выше код, я получаю выходные данные 4 и 8. Но мой друг скомпилировал и выполнил тот же код на своей машине, и у него были выходные данные 4 и 4. Я не знаю, почему это происходит и почему репетитор использовал sizeof для указателя на переменную вместо самой переменной, так как он хотел знать объем памяти, занимаемый этой переменной. Я знаю, что переменные в C / C ++ имеют различную емкость памяти из-за разной архитектуры, по крайней мере, так меня учили в C. То, что int в 64-битной машине имеет другой размер по сравнению с 32-битной. Но я думаю, что мои результаты должны быть как минимум согласованными, т.е. 8 и 8, или 4 и 4. Я использую 64-битную архитектуру и 64-битную ОС, мой друг использует 64-битную архитектуру с 32-битной ОС.
Решение
дает вам размер переменной p , который имеет тип int * ,
Это не такой же как
который даст вам размер, занимаемый int переменная.
Сказав, что, просто чтобы уточнить, чтобы узнать размер, занимаемый переменной, вам нужно использовать sizeof оператор этой переменной, а не указатель на эту переменную. ( Что вы узнали в первый год является правильный ).
Обратите внимание, что размер указателя зависит от архитектуры, поэтому он может варьироваться. В некоторых архитектурах размер указателя может быть 32 бита ( sizeof вернет 4), в некоторых других это может быть 64 бит ( sizeof вернется 8).
Другие решения
Вы должны использовать sizeof к самому значению, чтобы узнать, сколько памяти занято переменной. Я думаю, что репетитор сделал неправильно.
sizeof(ptr) дает размер указателя ptr и его размер определяется реализацией. То же самое верно для sizeof(int) , Вот почему вы и ваш друг получаете разные результаты.
Другие возможности, которые вы можете получить в виде 4 4 а также 8 8 ,
Из стандартной тяги N 3690:
« sizeof Оператор возвращает количество байтов в объектном представлении своего операнда. Операнд
либо выражение, которое является неоцененным операндом (раздел 5), либо идентификатор типа в скобках. sizeof
оператор не должен применяться к выражению, имеющему функцию или неполный тип, к типу перечисления
базовый тип которого не зафиксирован до объявления всех перечислителей в массиве времени выполнения
привязано к названию таких типов в скобках или к значению glvalue, обозначающему битовое поле. sizeof(char) ,
sizeof(signed char) а также sizeof(unsigned char) 1. Результат sizeof применяется к любому другому
Фундаментальный тип (3.9.1) определяется реализацией. «
Для компилятора все указатели имеют фиксированный размер независимо от типа данных.
Размер указателя в 32-битном компьютере составляет 4 байта, а в 64-битном размер указателя составляет 8 байтов. Вот почему ваш друг получает 4 в качестве размера указателя, а вы получаете 8.
После запуска средства можно увидеть пути выполнения функций, для которых выделяются объекты. Затем можно проследить путь к корню дерева вызовов, который использует больше всего памяти.
Установка
Откройте профилировщик производительности (ALT+F2) в Visual Studio.
После его запуска просмотрите сценарий, который вы хотите профилировать в приложении. Затем выберите Остановить сбор или закройте приложение, чтобы просмотреть данные.
Щелкните вкладку Выделение. Теперь содержимое окна должно выглядеть как на снимке экрана ниже.
Теперь вы можете проанализировать выделение памяти объектам.
Во время сбора средство отслеживания может замедлить работу профилированного приложения. Если производительность средства отслеживания или приложения замедлена и если не требуется отслеживать каждый объект, можно настроить частоту выборки. Для этого на странице сводки профилировщика рядом со средством отслеживания щелкните значок шестеренки.
Настройте необходимую частоту выборки. Такое изменение улучшит производительность приложения во время сбора и анализа.
Дополнительные сведения о том, как сделать средство более эффективным, см. в статье Оптимизация параметров профилировщика.
Анализ данных
В предыдущем графическом представлении на верхнем графе показано количество активных объектов в приложении. На нижнем графе Object delta (Изменение объекта) показано процентное изменение объектов приложения. Красные столбцы обозначают, что была проведена сборка мусора.
Можно отфильтровать табличные данные, чтобы отображать действия только для указанного диапазона времени. Можно также увеличивать или уменьшать граф.
Выделение
В представлении Выделение показано местонахождение объектов, которым выделена память, и объем выделенной им памяти.
Столбец Тип содержит список классов и структур, занимающих память. Дважды щелкните тип, чтобы просмотреть его обратную трассировку в виде инвертированного дерева вызовов. Только в представлении Выделение можно просмотреть элементы в выбранной категории, занимающей память.
В столбце Выделения показано количество занимающих память объектов, относящихся к определенному типу выделения или функции. Этот столбец отображается только в представлениях Выделение, Дерево вызовов и Функции.
Столбцы Байты и Средний размер (байты) по умолчанию скрыты. Чтобы их отобразить, щелкните правой кнопкой мыши столбец Тип или Выделения, а затем выберите параметры Байты и Средний размер (байты) , чтобы добавить их в диаграмму.
Эти два столбца похожи на Всего (выделения) и Собственные (выделения) за тем исключением, что вместо количества объектов, занимающих память, в них показан общий объем занимаемой памяти. Эти столбцы отображаются только в представлении Выделение.
В столбце Имя модуля показан модуль, содержащий вызывающую функцию или процесс.
Все эти столбцы можно сортировать. Для столбцов Тип и Имя модуля можно сортировать элементы в алфавитном порядке по возрастанию или убыванию. Для столбцов Выделения, Байты и Средний размер (байт) можно сортировать элементы по увеличению или уменьшению числовых значений.
Символы
На вкладках Выделение, Дерево вызовов и Функции отображаются следующие символы:
— тип значения, например целое число.
— коллекция типа значения, например массив целых чисел.
— ссылочный тип, например строка.
— коллекция ссылочного типа, например массив строк.
Дерево вызовов
В представлении Дерево вызовов отображаются пути выполнения функций, содержащие объекты, для которых выделяется много памяти.
В столбце Имя функции показан процесс или имя функции, содержащей объекты, для которых выделяется память. Отображение зависит от уровня проверяемого узла.
В столбцах Всего (выделения) и Общий размер (байты) отображается количество выделенных объектов и объем памяти, используемые функцией и всеми другими функциями, которые она вызывает.
В столбцах Self (Allocations) (Собственные (выделения)) и Self-Size (Bytes) (Собственный размер (байт)) отображается количество выделенных объектов и объем памяти, используемый одной выбранной функцией или типом выделения.
В столбце Average Size (Bytes) (Средний размер (байт)) отображаются те же сведения, что и в представлении Выделения.
В столбце Имя модуля показан модуль, содержащий вызывающую функцию или процесс.
При нажатии кнопки Развернуть критический путь высвечивается путь выполнения функции, содержащий множество объектов, для которых выделяется память. Алгоритм высвечивает путь с наибольшим количеством выделений, начиная с выбранного узла, помогая изучать использование памяти.
Кнопка Показать критический путь отображает или скрывает значки пламени, указывающие, какие узлы входят в критический путь.
Функции
В представлении Функции показаны процессы, модули и функции, для которых выделяется память.
В столбце Имя отображаются процессы в качестве узлов верхнего уровня. Под процессами располагаются модули, а под ними — функции.
В этих столбцах приводятся те же сведения, что и в представлениях Выделение и Дерево вызовов:
- Total (Allocations) (Всего (выделения));
- Self (Allocations) (Собственные (выделения));
- Общий размер (байт) ;
- Self-Size (Bytes) (Собственный размер (байт));
- Average Size (Bytes) (Средний размер (байт)).
Collection
В представлении Коллекция показано, сколько объектов было собрано или осталось во время сборки мусора. В нем также имеются круговые диаграммы для визуализации собранных и сохранившихся объектов по типу.
- В столбце Собрано показано количество объектов, собранных сборщиком мусора.
- В столбце Осталось показано количество объектов, сохранившихся после работы сборщика мусора.
Средства фильтрации
В каждом из представлений Выделения, Дерево вызовов и Функции есть параметры Показать только мой код и Show Native Code (Показать машинный код), а также поле фильтра.
С помощью встроенного в отладчик средства диагностики Использование памяти вы сможете находить утечки памяти и выявлять ее неэффективное использование. С помощью средства "Использование памяти" можно сделать один или несколько снимков управляемой и собственной памяти в куче, чтобы понять влияние использования памяти типов объектов. Анализировать использование памяти также можно без подключения отладчика — нужно просто указать выполняющееся приложение. Дополнительные сведения см. в разделе Запуск средств профилирования с отладчиком или без него. Сведения о выборе необходимого средства анализа памяти см. в разделе Выбор инструмента для анализа памяти.
Хотя с помощью средства Использование памяти можно делать снимки памяти в любой момент, для управления выполнением приложения во время анализа ошибок производительности вы можете использовать отладчик Visual Studio. Задание точек останова, пошаговое выполнение, всеобщее прерывание и другие действия отладчика могут помочь вам сосредоточиться на анализе производительности при обращении к наиболее важным ветвям кода. Выполняя эти действия, когда приложение запущено, вы сможете исключить влияние не интересующего вас кода и значительно ускорить диагностику проблем.
В этом руководстве рассмотрены следующие задачи:
- Создание моментальных снимков с данными об использовании памяти
- Анализ данных использования памяти
Если средство Использование памяти не предоставляет необходимые данные, можно воспользоваться другими средствами профилирования в Профилировщике производительности, предоставляющими другие виды информации, которая может оказаться полезной. Как правило, проблемы производительности приложения могут вызываться другими компонентами помимо памяти, такими как ЦП, отрисовка пользовательского интерфейса или время запроса сети.
Поддержка пользовательского распределителя. Профилировщик внутренней памяти работает путем сбора данных событий ETW выделения памяти, создаваемых во время выполнения. Распределители в CRT и пакете Windows SDK аннотированы на уровне исходного кода, что позволяет регистрировать их данные выделения. Если вы создаете собственные распределители, любые функции, возвращающие указатель на только что выделенную память в куче, можно декорировать с использованием __declspec(allocator), как показано в этом примере для myMalloc:
__declspec(allocator) void* myMalloc(size_t size)
Сбор данных об использовании памяти
Откройте проект для отладки в Visual Studio и установите точку останова в приложении в точке, где вы хотите начать проверку использования памяти.
Если вы подозреваете, что в определенной области памяти может возникнуть проблема, задайте первую точку останова до ее возникновения.
Так как из-за изменений в объеме выделяемой памяти создание профиля памяти для интересующей вас операции может быть затруднительно, разместите точки останова в начале и в конце операции или пройдите по ней, чтобы попробовать найти точку, в которой объем памяти изменился.
Установите вторую точку останова в конце функции или области кода, который требуется проанализировать, либо после возникновения предполагаемой проблемы с памятью.
Окно Средства диагностики появится автоматически, если вы не отключали эту функцию. Чтобы снова открыть окно, щелкните Отладка > Окна > Показать средства диагностики.
На панели инструментов выберите Использование памяти, применяя параметр Выбор средств.
Щелкните Отладка | Начать отладку (Запустить на панели инструментов или F5).
По завершении загрузки приложения отображается представление "Сводка" средств диагностики.
Поскольку сбор данных об использовании памяти может повлиять на производительность отладки приложений, основанных на машинном коде, а также смешанных программ, по умолчанию снимки памяти выключены. Чтобы включить моментальные снимки для приложений на базе машинного кода или для смешанных программ, начните сеанс отладки (клавиша: F5). Когда отобразится окно Средства диагностики, перейдите на вкладку Использование памяти и выберите Профилирование кучи.
Остановите (сочетание клавиш: SHIFT+F5) и перезапустите отладку.
Поскольку сбор данных об использовании памяти может повлиять на производительность отладки приложений, основанных на машинном коде, а также смешанных программ, по умолчанию снимки памяти выключены. Чтобы включить моментальные снимки для приложений на базе машинного кода или для смешанных программ, начните сеанс отладки (клавиша: F5). Когда отобразится окно Средства диагностики, перейдите на вкладку Использование памяти и выберите Профилирование кучи.
Остановите (сочетание клавиш: SHIFT+F5) и перезапустите отладку.
Чтобы сделать моментальный снимок в начале сеанса отладки, на сокращенной панели инструментов Использование памяти выберите команду Сделать снимок. (Таким образом здесь также можно задать точку останова.)
Чтобы получить базовые показатели для сравнения состояния памяти, сделайте снимок в начале сеанса отладки.
Запустите сценарий, который вызвал срабатывание первой точки останова.
После приостановки отладчика на первой точке останова на сокращенной панели инструментов Использование памяти выберите команду Сделать снимок.
Нажмите клавишу F5, чтобы запустить приложение до второй точки останова.
Теперь создайте еще один моментальный снимок.
На этом этапе можно начать анализировать данные.
Анализ данных использования памяти
В строках сводной таблицы "Использование памяти" приводятся моментальные снимки, сделанные во время сеанса отладки, и ссылки на дополнительные подробные представления.
Если сделать несколько снимков, в каждой строке сводной таблицы будет отображаться разница значений с предыдущим снимком.
Чтобы выполнить анализ данных об использовании памяти, щелкните одну из ссылок, которая позволяет открыть подробный отчет об использовании памяти:
- Чтобы отобразить подробности об изменении текущего моментального снимка по сравнению с предыдущим, щелкните ссылку разницы слева от стрелки (). Красная стрелка обозначает, что объем используемой памяти увеличился, а зеленая — что он снизился.
Чтобы быстрее выявить проблемы с памятью, типы объектов в отчетах об изменениях можно отсортировать по наибольшему увеличению общего объема (щелкните ссылку "Изменения" в столбце Объекты (разн.) ) или по наибольшему увеличению размера кучи (щелкните ссылку "Изменения" в столбце Размер кучи (разн.) ).
Чтобы отобразить подробности только для выбранного моментального снимка, щелкните ссылку "Без изменений".
Отчет отображается в новом окне.
Отчеты об управляемых типах
Щелкните текущую ссылку в ячейке Объекты (разн.) или Выделения (разн.) в сводной таблице "Использование памяти".
В дереве Объекты, на которые указывает ссылка отображаются ссылки, активные для выбранного в верхней области типа.
В дереве Типы, на которые указывает ссылка отображаются ссылки, активные для выбранного в верхней области типа.
Чтобы отобразить экземпляры типа, выбранного в верхней области, нажмите кнопку "Просмотреть экземпляры" рядом с типом объекта.
На панели Экземпляры , которая открывается в верхней области, отображаются экземпляры выбранного объекта текущего снимка. На панелях Пути к корню и Объекты, на которые указывает ссылка отображаются объекты, которые ссылаются на выбранный экземпляр, а также типы, на которые ссылается выбранный экземпляр. Если создать снимок после остановки отладчика и навести указатель мыши на ячейку в столбце Значение, во всплывающей подсказке отобразятся значения объекта.
Отчеты о собственных типах
Щелкните текущую ссылку в ячейке Выделения (разн.) или Размер кучи (разн.) в сводной таблице "Использование памяти", отображаемой в окне Средства диагностики.
В окне Экземпляры отображаются все экземпляры выбранного типа. При выборе экземпляра на панели Стек вызовов выделений отображается стек вызовов, использованный для создания этого экземпляра.
В окне Экземпляры отображаются все экземпляры выбранного типа. При выборе экземпляра на панели Стек вызовов выделений отображается стек вызовов, использованный для создания этого экземпляра.
Чтобы отобразить стек вызовов для выбранного типа, в раскрывающемся меню Режим просмотра выберите пункт Представление стеков .
Чтобы отобразить стек выделений для выбранного типа, выберите Стеки.
Отчеты об изменениях
В окне Средства диагностики щелкните в необходимой ячейке сводной таблицы Использование памяти разницу в значениях.
Выберите моментальный снимок в списке Сравнить с , в котором отображаются управляемые или собственные отчеты.
С помощью отчета об изменениях в основной отчет можно добавить столбцы, помеченные надписью (Разн.) , в которых будет отображаться разница между двумя выбранными снимками. Отчет об изменениях собственных типов может выглядеть следующим образом.
Блоги и видео
Следующие шаги
В этом руководстве вы узнали, как собирать и анализировать данные об использовании памяти. Если вы уже ознакомились с общими сведениями о профилировщике, можно перейти к анализу данных об использовании ЦП в приложениях.
Перехватывать new и delete ? сомнительно, не очень верится, что все будет работать только через эти операторы.
Словом, никто не подскажет, как все-таки лучше, надежнее и точнее всего это делать, причем желательно не извне, а из самой программы?
Конкретнее - Windows, использую Visual C++ 2017.
Как посмотреть затрачиваемые ресурсы программы? сообщала о самых разнообразных ошибках - ошибки в студию
@user7860670 Уже завтра, сегодня голова уже не варит. Тот проект я уже прибил, заводиться с нуля сейчас не хочу.
Использую VS2015 pro, в отладчике есть отличная штука - Diagnostic Tools, которая позволяет снять снепшот памяти и проанализировать, чего и в каких количествах в ней выделялось. (Подозреваю, что VS2017 должна обладать этой тулзой тоже - в отладчике меню Debug->Windows->Show Diagnostic Tools)
1 ответ 1
Для получения информации о памяти процесса есть несколько API, наиболее интересны из них:
Показатели, которые я здесь использую:
Private committed memory (Частная выделенная память) - объем виртуальной памяти процесса в состоянии MEM_COMMIT, принадлежащей исключительно этому процессу. Состояние MEM_COMMIT значит, что под данную память выделено место в файле подкачки, а в физической памяти оно может быть либо выделено, либо нет. Из данного значения исключена память, которая является разделяемой между разными процессами - отображенные на память файлы и загруженные DLL, отсюда "private". Звучит сложно, но по сути это и есть главный показатель, сколько процесс "жрет" памяти.
Working set (Рабочий набор) - общий объем физической памяти, выделенной процессу, в том числе разделяемой между несколькими процессами.
Private working set (Частный рабочий набор) - объем физической памяти, принадлежащей исключительно данному процессу. Этот показатель более полезен, чем предыдущий, но получить его сложнее.
Heap size - объем выделенной динамической памяти (помимо непосредственно выделенного нами через new , включает также то, что выделено внутренне библиотеками).
Какой из этих показателей использовать, сильно зависит от ситуации. Если речь о спортивном программировании и ограничении количества используемой памяти на решение задачи, интересен Private committed memory. Если же речь идет об оценке нагрузки на систему, важнее показатели физической памяти, так как она более дефицитна, чем место в файле подкачки.
Мне интересно, как я могу точно рассчитать, сколько памяти займет моя программа, и из какой памяти (RAM, register,…). Наиболее очевидным является все, что я выделяю через malloc. Извините, если следующие вопросы немного случайны…
- Глобальные переменные будут храниться в ОЗУ? Влияет ли ключевое слово static (ограничить область) на что-либо?
- Выделяются ли все глобальные переменные одновременно или могут быть ленивы распределены при первом доступе?
- Загружен ли исполняемый файл в память? Выполняет ли исполняемый файл 1 МБ 1 МБ для выполнения?
Этот предмет довольно большой, поэтому не стесняйтесь указывать мне книгу или сайт. Я думаю, это не только о C, но и больше об архитектуре компьютера, ассемблере и т.д.
Я предполагаю типичные вычислительные платформы, а не встроенные системы.
Глобальные переменные будут храниться в ОЗУ? Влияет ли ключевое слово static (ограничить область) на что-либо?
Глобальные переменные будут храниться в ОЗУ только в том случае, если операционная система думает, что лучше всего использовать ОЗУ. Область действия не влияет.
Выделяются ли все глобальные переменные одновременно или могут быть ленивы распределены при первом доступе?
Это зависит от того, что вы подразумеваете под “выделенным”. Обычно виртуальная память (адресное пространство) выделяется сразу, но при необходимости выделяется физическая память (ОЗУ).
Загружен ли исполняемый файл в память? Выполняет ли исполняемый файл 1 МБ 1 МБ для выполнения?
Он отображается в память при запуске программы. Он фактически загружается в физическую память по мере необходимости и вывозится из физической памяти по мере того, как ОС сочтет это уместным.
Я сильно подозреваю, что вы ищете простые ответы на очень сложные вопросы.
- Да, но это не значит, что все они отображаются в любой момент времени.
- Они не могут быть лениво распределены, в зависимости от того, что вы подразумеваете под этим. Все они будут сопоставлены с виртуальными адресами, но опять же, если программа никогда не обратится к переменным, OS может никогда не понадобиться для сопоставления этих адресов с фактической физической оперативной памятью.
- Это зависит, но, по-моему, большинство современных настольных/серверных операционных систем будут писать код по мере необходимости.
Oups, это интересный вопрос, но ответ как обычно: это зависит!
Ваши вопросы сильно зависят от реализации. В старых (теперь устаревших) системах существовало понятие оверлеев: части кода были загружены только в память, когда это необходимо. Я не думаю, что он по-прежнему используется с современными системами виртуальной памяти, но он может иметь смысл для встроенных систем с неограниченными ресурсами.
И некоторые компиляторы обычно имеют опции для определения размера стека. Это может быть определяющим для облегченной программы.
Читайте также: