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;
}