Альтернативный способ получить оценку использования стека - прочитать значение указателя стека в каждой функции и обновить переменные минимального и максимального указателя стека.В конце программы разница между двумя значениями даст вам оценку.
Чтобы прочитать значение указателя стека, вы можете:
- Реализовать функцию сборки(делает
mov r/eax, r/esp
+ ret
для процессора x86) - Сделайте то же самое (без повторов, конечно), используя встроенную сборку, если поддерживается вашим компилятором
- Реализуйте что-то вродениже (который может работать не всегда / везде из-за оптимизации кода)
Код:
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
// uintptr_t is an unsigned integer type from stdint.h
// that is capable of holding a pointer.
// If you don't have it in your compiler, use an
// equivalent, which may be size_t (stddef.h) or
// UINT_PTR (windows.h) or something else.
uintptr_t StackPointerMin = (uintptr_t)-1;
uintptr_t StackPointerMax = 0;
void UpdateStackUsageInner(int dummy, ...)
{
va_list ap;
volatile char* p;
uintptr_t StackPointer;
va_start(ap, dummy);
p = va_arg(ap, volatile char*);
StackPointer = (uintptr_t)p;
if (StackPointer < StackPointerMin) StackPointerMin = StackPointer;
if (StackPointer > StackPointerMax) StackPointerMax = StackPointer;
va_end(ap);
}
void UpdateStackUsage()
{
volatile char c = 'a';
UpdateStackUsageInner(0, &c);
}
void DoSomething(void)
{
char c[1024+1];
UpdateStackUsage();
memset(c, '*', sizeof(c));
c[sizeof(c)-1] = '\0';
printf("%s\n", c);
}
int main(void)
{
UpdateStackUsage();
DoSomething();
printf("Approximate stack usage: %lu\n",
(unsigned long)(StackPointerMax - StackPointerMin));
return 0;
}
Вывод:
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
****************************************************************
Approximate stack usage: 1040
Я также знаю, что некоторыекомпиляторы поддерживают ввод функции перехвата (и, возможно, выход), что может упростить задачу, поскольку при этом вам не нужно будет вставлять UpdateStackUsage();
во все / многие ваши функции.Это обсуждалось здесь .