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

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

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

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

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

Спасибо!

1 Ответ

0 голосов
/ 04 мая 2020

Довольно скучным / хакерским способом может быть обнаружение начала стека вызовов непосредственно перед вызовом функции 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, но это не должно быть так сложно.

...