堆栈与函数调用 作者 xgywinner 日期 2009-3-18 11:44:00
1) 在栈上创建。在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,一般使用寄存器来存取,效率很高,但是分配的内存容量有限。 经典实例:(代码来自网络高手,没有找到原作者) ![]() #i nclude <string> int a=0; //全局初始化区 char *p1; //全局未初始化区 void main() { int b;//栈 char s[]="abc"; //栈 char *p2; //栈 char *p3="123456"; //123456\0在常量区,p3在栈上。 static int c=0; //全局(静态)初始化区 p1 = (char*)malloc(10); p2 = (char*)malloc(20); //分配得来得10和20字节的区域就在堆区。 strcpy(p1,"123456"); //123456\0放在常量区,编译器可能会将它与p3所向"123456\0"优化成一个地方。 }
二 三种内存对象的比较
实际上,被转化成这样:
除了全局静态对象,还有局部静态对象通和class的静态成员,局部静态对象是在函数中定义的,就像栈对象一样,只不过,其前面多了个static关键字。局部静态对象的生命期是从其所在函数第一次被调用,更确切地说,是当第一次执行到该静态对象的声明代码时,产生该静态局部对象,直到整个程序结束时,才销毁该对象。class的静态成员的生命周期是该class的第一次调用到程序的结束。 三 函数调用与堆栈 1)编译器一般使用栈来存放函数的参数,局部变量等来实现函数调用。有时候函数有嵌套调用,这个时候栈中会有多个函数的信息,每个函数占用一个连续的区域。一个函数占用的区域被称作帧()。同时栈是线程独立的,每个线程都有自己的栈。例如下面简单的函数调用: 另外函数堆栈的清理方式决定了当函数调用结束时由调用函数或被调用函数来清理函数帧,在VC中对函数栈的清理方式由两种:
2) 有了上面的知识为铺垫,我们下面细看一个函数的调用时堆栈的变化: 代码如下:
![]() int Add(int x, int y) { return x + y; } void main() { int *pi = new int(10); int *pj = new int(20); int result = 0; result = Add(*pi,*pj); delete pi; delete pj; }
对上面的代码,我们分为四步,当然我们只画出了我们的代码对堆栈的影响,其他的我们假设它们不存在,哈哈! 第一,int *pi = new int(10); int *pj = new int(20); int result = 0; 堆栈变化如下: 第二,Add(*pi,*pj);堆栈如下: 第三,将Add的结果给result,堆栈如下: 第四,delete pi; delete pj; 堆栈如下: 第五,当main()退出后,堆栈如下,等同于main执行前,哈哈!
四 完! |
堆栈与函数调用
|