当前位置:网站首页>一种简单通用的获取函数栈空间大小的方法
一种简单通用的获取函数栈空间大小的方法
2022-07-29 03:11:00 【星沉地动】
有些时候我们需要评估某个函数所使用的栈空间大小,比如创建线程的时候,我们需要估算该线程函数所需的栈空间,分配合适的线程栈。
本文介绍一种简单的方法,来获取某个函数所占用的栈空间大小。
原理:
针对递减栈内存模型,调用函数时,栈指针会往下移动,移动的距离取决于该函数的局部变量和调用子函数,也就是该函数所使用的栈空间,在函数返回时,栈指针又会恢复到调用前的位置。
根据这一特性,我们可以在调用函数前把栈底部的内存用一个特定值来填充,调用结束后检查栈底部的值是否发生变化,搜索到最后1个发生变化的地址就是该函数所使用的栈底。用当前栈指针减去栈底指针就能算出该函数实际使用的栈空间大小。
实施:
废话不多说,直接上测试代码:
//用0xAA填充栈底512字节
void stack_test_begin(void)
{
register int i;
unsigned char mem[512];
for(i = 0; i < 512; i++)
{
mem[i] = 0xAA;
}
}
//检查栈底,返回栈大小
int stack_test_end(void)
{
register int i;
unsigned char mem[512];
for(i = 0; i < 512; i++)
{
if(mem[i] != 0xAA)
{
return 512 - i;
}
}
return 0;
}
//被测试函数, 此函数理论占用栈空间为128字节
void stack_use_128(void)
{
register int i;
char mem[128];
for(i=0; i<128; i++)
{
mem[i] = 0;
}
}
//测试
void main(void)
{
int stack_size;
stack_test_begin();
stack_use_128();
stack_size = stack_test_end();
printf("stack: %d\n", stack_size);
}
代码解读:
为方便分析,假设main函数的初始栈指针为SP=0x00001000。
1. 调用stack_test_begin() ,这个函数局部变量mem占用512字节,这512字节用0xAA填充,实际就会导致0x00000E00 - 0x00001000被填充为0xAA。这就完成了我们栈底填充特定值步骤。
2. 调用stack_use_128(),这个函数是我们想要获取栈空间的目标函数,这个函数对局部变量的操作,会导致我们填充的0xAA变为其它值。
3.调用stack_test_end(),这个函数同样使用512字节的局部变量,我们搜索这512字节空间,从前往后找,找到不是0xAA的值,就表示此处是被stack_use_128()函数使用的栈边界。此边界之前是未用到的栈内存,因此用512减去此边界值就是该函数实际使用的栈空间大小。
4.如果被测函数栈空间超过512,则需要把512改为更大的值,增加更多的填充深度。
总结:
此方法在ARM和x86平台上测试能正常工作。不依赖系统调用,通用性较强。
但填充内存和搜索内存会消耗CPU资源,影响整体性能,因此只适合在代码调试阶段使用。
完
边栏推荐
- [NPM error] - NPM err code eresolve and NPM err eresolve could not resolve problems
- 04 | 后台登录:基于账号密码的登录方式(上)
- Data truncation and estimation
- 12_ UE4 advanced_ Change a more beautiful character model
- 百度副总裁李硕:数字技术加持下中国劳动力成本上升是好事
- Unity 之游戏特效
- Verilog:阻塞赋值和非阻塞赋值
- C traps and defects Chapter 3 semantic "traps" 3.1 pointers and arrays
- C traps and defects Chapter 3 semantic "traps" 3.3 array declaration as parameters
- Server operation management system
猜你喜欢
随机推荐
Verilog's time system tasks - $time, $stime, $realtime
爆肝整理JVM十大模块知识点总结,不信你还不懂
西瓜书学习第六章---SVM
服务器运行管理制度
C traps and defects Chapter 3 semantic "traps" 3.2 pointers to non arrays
MySQL large table joint query optimization, large transaction optimization, avoiding transaction timeout, lock wait timeout and lock table
【C】 Array
MYSQL入门与进阶(十二)
MySQL compound query (important)
C and pointer Chapter 3 semantic "trap" 3.5 null pointer is not a string
12_ UE4 advanced_ Change a more beautiful character model
4000 多字学懂弄通 js 中 this 指向问题,顺便手写实现 call、apply 和 bind
JVM基础入门篇一(内存结构)
Incremental real-time disaster recovery notes
【打开新世界大门】看测试老鸟如何把API 测试玩弄在鼓掌之间
算法---粉刷房子(Kotlin)
融云 IM & RTC 能力上新盘点
What is eplato cast by Plato farm on elephant swap? Why is there a high premium?
Learn more than 4000 words, understand the problem of this pointing in JS, and handwrite to realize call, apply and bind
Typescript学习(一)