2017 09 16 23 43 [c] 檢查stack size

因為最近遇到stack overflow的case,
所以想說要來寫個可以印出最大使用的stack size.
剛好可以利用gcc的特異功能, 來印出目前最大的stack size.
只是目前有個limitation是只能用在single thread.
如果要用在multi-thread,這個source code還需要做某些修改才行.
還有,要算更精準的stack size,
還需要再去掉 call __cyg_profile_func_exit 本身用掉的 stack,
不過以我目前的需求是這樣就夠用了.

#include <stdio.h>
#include <stdlib.h>

void *main_func = NULL;
char *stack_base = NULL;
int  max_stack_size = 0;

void __attribute__((__no_instrument_function__))
__cyg_profile_func_enter(void *this_func, void *call_site)
{
  char x;
  if (main_func == NULL) {
      main_func = this_func;
  }
  if (stack_base == NULL) {
      stack_base = &x;
  }
}

void __attribute__((__no_instrument_function__))
__cyg_profile_func_exit(void *this_func, void *call_site)
{
  char x;
  int  s;

s = (int)(stack_base - &x); if (s > max_stack_size) { max_stack_size = s; } if (main_func == this_func) { printf("stack size = 0x%x\n",max_stack_size); } } int test() { unsigned int buf[0x100-4]; int i; buf[0]=1; buf[1]=1; for (i=2;i<sizeof(buf)/sizeof(buf[0]);i++) { buf[i]=buf[i-1]+buf[i-2]; } printf("<%u>\n",buf[sizeof(buf)/sizeof(buf[0])-1]); return 0; } int main() { return test(); }
root@linux:/tmp# gcc  -finstrument-functions test.c
root@linux:/tmp# ./a.out
<814472144>
stack size = 0x424

後來發現新的問題,
如果你在 __cyg_profile_func_enter 或 __cyg_profile_func_exit 裡面呼叫到inline function,
就會發生慘劇.
因為inline function的關係, 所以本身所插的code去呼叫這兩個functions, 也會被inline進去,
其結果是crash. 因為本身會一直call __cyg_profile_func_enter or __cyg_profile_func_exit.
解決這個問題的方式是:
在兩個functions __cyg_profile_func_enter 和 __cyg_profile_func_exit 前面檢查this_func是不是就是自己本身,
如果是的話,就直接return, 來避免無窮無盡的呼叫到自己.

if (this_func == __cyg_profile_func_enter || this_func == __cyg_profile_func_exit) {
return;
}