Как измерить размер стека функций для программы C в Visual Studio?

У меня есть очень большой проект C, который в настоящее время существует в решении Visual Studio. Я использую Visual Studio 2015. Каждый компонент проекта содержится в собственном проекте Visual Studio. У каждого компонента есть функции "init" и "run", которые вызываются в цикле while. В частности, у меня есть один компонент, где я хочу измерить размер стека его функции «запустить». В идеале я бы изменил конкретный параметр этой функции запуска и посмотрел, как это повлияет на память в дальнейшем (поэтому запустите несколько профилирования). Для GCC я обнаружил, что вы можете использовать fstack-usage, и это дает почти то, что я хотел бы: потребление памяти (то есть размер стека) каждой функции в программе. Однако большинство решений, которые я нашел в Интернете, применимы только к системам Linux. Я также настоятельно предпочел бы не переносить свое решение VS на другую платформу.

Однако в VS я не нашел инструмента, API или чего-то подобного. Профилировщик производительности VS вроде делает то, что я хочу, но он не предоставляет память каждой функции, а только память всего процесса, что не идеально для профилирования компонента. на основе проекта. Есть ли инструмент или метод в Visual Studio, с помощью которого я могу измерить размер стека функций для всех возможных функций? Я не против написать свой собственный инструмент, но я бы предпочел что-то относительно простое.

Здесь я также должен указать, что мне не нужна вся память процесса или размер стека вызовов. т.е. он должен распечатать что-то вроде этого:

Function Name | Stack Size
--------------|------------
a_Run         | 10.5 KB
b_Run         |  5.7 KB

Спасибо!


person Darren C.    schedule 06.01.2020    source источник


Ответы (1)


Довольно громоздкий/хакерский способ может состоять в том, чтобы определить начало стека вызовов непосредственно перед вызовом функции run и поместить водяной знак в фиксированный диапазон с самого начала. Затем, когда run завершится, снова пройдитесь по диапазону памяти с водяными знаками и определите, где водяной знак все еще присутствует, а где он был заменен фактическим использованием стека функцией запуска.

Чтобы определить начало стека, вы можете сделать:

// before calling run
#define MAX_CALL_STACK 1024
volatile int start; // declare just before calling run
// fill from &start to something with a known pattern.
// the trick is to ensure no other stack allocation is performed here
register int i;
register int &add = &start;
for (i = 0 i<MAX_CALL_STACK ;i++)
{
  *add = 0xdeadbeef; a++;
}    
run(); // this will replace deadbeaf values up to a given address
printf ("run call stack start address:0x%p",(void*)&start);

Скомпилированный код водяных знаков должен быть проверен, чтобы убедиться, что он действительно использует регистры и не объявляет никакие другие локальные переменные перед вызовом run.

Я не показывал, как обнаружить пространство 0xdeadbeef, но это не должно быть таким сложным.

person Jean-Marc Volle    schedule 04.05.2020