Как измерить использование стека функций в C?
есть ли способ измерить, сколько стековой памяти использует функция?
этот вопрос не относится к рекурсивным функциям; однако мне было интересно узнать, сколько стековой памяти займет функция, называемая рекурсивно.
мне было интересно оптимизировать функцию для использования стековой памяти; однако, не зная, какие оптимизации компилятор уже делает, это просто догадка, если это делает реальные улучшения или нет.
в будьте ясны, это не вопрос о том, как оптимизировать для лучшего использования стека
Итак, есть ли надежный способ узнать, сколько стековой памяти использует функция в C?
Примечание: предполагая, что он не использует alloca
или массивы переменной длины,
это должно быть возможно найти во время компиляции.
3 ответов
используя предупреждения
это специфический GCC (протестировано с gcc 4.9):
добавьте это над функцией:
#pragma GCC diagnostic error "-Wframe-larger-than="
, который сообщает об ошибках, таких как:
error: the frame size of 272 bytes is larger than 1 bytes [-Werror=frame-larger-than=]
хотя немного странный способ, вы можете, по крайней мере, сделать это быстро при редактировании файла.
используя переменные CFLAGS
вы можете добавить -fstack-usage
в ваши CFLAGS, которые затем записывают текстовые файлы вдоль сторон объектных файлов.
Видеть: https://gcc.gnu.org/onlinedocs/gnat_ugn/Static-Stack-Usage-Analysis.html
Хотя это работает очень хорошо, это может быть немного неудобно в зависимости от вашей buildsystem/configuration - построить один файл с другим CFLAG, хотя это, конечно, может быть автоматизировано.
- (благодаря комментарию @nos)
Примечание
кажется, что большинство / все естественные методы компилятора полагаются на угадывание , которое не 100% обязательно останется точным после оптимизации, так что это, по крайней мере, дает окончательный ответ с помощью бесплатного компилятора.
вы можете очень легко узнать, сколько пространства стека занимает вызов функции, которая имеет только одно слово локальных переменных следующим образом:
static byte* p1;
static byte* p2;
void f1()
{
byte b;
p1 = &b;
f2();
}
void f2()
{
byte b;
p2 = &b;
}
void calculate()
{
f1();
int stack_space_used = (int)(p2 - p1);
}
(Примечание: функция объявляет локальную переменную, которая является только байтом, но компилятор обычно выделяет для нее целое машинное слово в стеке.)
таким образом, это покажет вам, сколько пространства стека занимает вызов функции. Чем больше локальных переменных вы добавляете в функцию, тем больше пространства стека это займет много времени. Переменные, определенные в разных областях внутри функции, обычно не усложняют ситуацию, поскольку компилятор обычно выделяет отдельную область в стеке для каждой локальной переменной без какой-либо попытки оптимизации на основе того факта, что некоторые из этих переменных могут никогда не сосуществовать.
чтобы вычислить использование стека для текущей функции вы можете сделать что-то вроде этого:
void MyFunc( void );
void *pFnBottom = (void *)MyFunc;
void *pFnTop;
unsigned int uiStackUsage;
void MyFunc( void )
{
__asm__ ( mov pFnTop, esp );
uiStackUsage = (unsigned int)(pFnTop - pFnBottom);
}