C/C++: 函数调用, 栈的大小是怎么被确定的
C/C++: 函数调用, 栈的大小是如何被确定的?
每个函数调用都要压栈,
栈用来存放局部变量和形参以及状态指针,
可是很多时候变量是按程序逻辑动态创建的, 编译器不可能知道函数块需要多少局部变量啊?
比如这样一个函数:
void test()
{
if(someCondition) {double a = 123.0;} else {int b = 456;} // 栈的大小应按sizeof(a) 还是 sizeof(b)计算?
}
或者, 是我理解有误, 栈的大小可以伸缩?
------解决方案--------------------
sizeof(a) + sizeof(b)
------解决方案--------------------
void test()
{
if(someCondition) {double a = 123.0;} else {int b = 456;} // 栈的大小应按sizeof(a) 还是 sizeof(b)计算?
}
----------------------
你要明确, 函数的所有局部变量都是进入函数的时候分配的. 并不是你定义的时候才分配!
所以, 无论 someCondition 是否成立, double a 和 int b 变量都会被分配. 而不是根据这个条件, 满足的时候分配 a, 不满足的时候分配 b.
------解决方案--------------------
------解决方案--------------------
没错函数调用的确是是个压栈的过程; 函数返回后,压栈的数据被弹出。
栈的大小,应该由编译器和os共同决定吧。
编译器中,有frame 和 record的概念。来控制函数调用和返回。以及发生异常时,栈的回退(unwinded)等。
函数调用中其相关信息和其局部变量的空间都在栈上分配,而且是编译器自动分配。
至于你说的是sizeof(a) 还是sizeof(b);个人觉得应该大于sizeof(a) + sizeof(b);
因为函数调用的过程,是一个上下文切换的过程,其间,首先要保存现场、然后将函数的返回地址及局部变量压栈、执行函数、返回、恢复现场。 如果写过汇编程序,这个就很容易理解了。
这些都是有编译器实现的,具体细节我们不必关心。
alloc 可以在栈上分配内存。你可以通过在函数内部定义一个足够大数组,来看看,你的编译器分配的stack size。
------解决方案--------------------
...
简单点 花点时间了解下ebp,esp寄存器的用途,用Ollydbg随便打开一个程序,单步跟踪下函数调用的过程,观察栈的变化 就明白了
------解决方案--------------------
这个兄弟解释的差不多。stack 和 stack frame弄清楚了就明白了。
建议学习一下linux内核。
每个函数调用都要压栈,
栈用来存放局部变量和形参以及状态指针,
可是很多时候变量是按程序逻辑动态创建的, 编译器不可能知道函数块需要多少局部变量啊?
比如这样一个函数:
void test()
{
if(someCondition) {double a = 123.0;} else {int b = 456;} // 栈的大小应按sizeof(a) 还是 sizeof(b)计算?
}
或者, 是我理解有误, 栈的大小可以伸缩?
------解决方案--------------------
sizeof(a) + sizeof(b)
------解决方案--------------------
void test()
{
if(someCondition) {double a = 123.0;} else {int b = 456;} // 栈的大小应按sizeof(a) 还是 sizeof(b)计算?
}
----------------------
你要明确, 函数的所有局部变量都是进入函数的时候分配的. 并不是你定义的时候才分配!
所以, 无论 someCondition 是否成立, double a 和 int b 变量都会被分配. 而不是根据这个条件, 满足的时候分配 a, 不满足的时候分配 b.
------解决方案--------------------
------解决方案--------------------
没错函数调用的确是是个压栈的过程; 函数返回后,压栈的数据被弹出。
栈的大小,应该由编译器和os共同决定吧。
编译器中,有frame 和 record的概念。来控制函数调用和返回。以及发生异常时,栈的回退(unwinded)等。
函数调用中其相关信息和其局部变量的空间都在栈上分配,而且是编译器自动分配。
至于你说的是sizeof(a) 还是sizeof(b);个人觉得应该大于sizeof(a) + sizeof(b);
因为函数调用的过程,是一个上下文切换的过程,其间,首先要保存现场、然后将函数的返回地址及局部变量压栈、执行函数、返回、恢复现场。 如果写过汇编程序,这个就很容易理解了。
这些都是有编译器实现的,具体细节我们不必关心。
alloc 可以在栈上分配内存。你可以通过在函数内部定义一个足够大数组,来看看,你的编译器分配的stack size。
------解决方案--------------------
...
简单点 花点时间了解下ebp,esp寄存器的用途,用Ollydbg随便打开一个程序,单步跟踪下函数调用的过程,观察栈的变化 就明白了
------解决方案--------------------
这个兄弟解释的差不多。stack 和 stack frame弄清楚了就明白了。
建议学习一下linux内核。