程序中的栈

栈是现代计算机程序里最为重要的概念之一
栈在程序中用于维护函数调用上下文
函数中的参数和局部变量存储在栈上
栈是一种行为,后进先出。
栈保存了一个函数调用所需的维护信息。

例如:参数、返回地址、局部变量、调用上下文、寄存器信息、其他数据信息

函数调用过程

每次函数调用都对应着一个栈上的活动记录
调用函数的活动记录位于栈的顶部
被调用的活动记录位于栈的顶部

函数调用的栈变化一
从main()调用f()

栈底main()参数
返回地址
ebp→old ebp
数据信息
f()参数
返回地址
old ebp
esp→数据信息

函数调用栈上的数据

函数调用时,对应的栈空间在函数返回前是专用的
函数调用结束后,栈空间将被释放,数据不再有效

千万不要返回局部变量的地址

在栈空间中,局部变量的地址会被销毁的,局部变量的地址是没有意义的。

例子39-1:

#include "stdio.h"
int* g()
{
    int a[10] = {0};
    return a;
}
void f()
{
  int i = 0;
  int b[10] = {0,1,2,3,4,5,6,7,8,9};
  int* pointer = g();
  for(i = 0; i <10; i++)
  {
     b[i] = pointer[i];
  }
  for( i = 0;i<10;i++)
  {
    printf("%d\n",b[i]);
  }
}
int main()
{
    f();
    return 0;
}

输出结果:

0
0
0
0
0
0
0
0
0
0
pointer所指的g()的返回值赋值给b,打印出结果

例子39-1修改:

#include "stdio.h"
int* g()
{
    int a[10] = {0};
    return a;
}
void f()
{
  int i = 0;
  int b[10] = {0,1,2,3,4,5,6,7,8,9};
  int* pointer = g();
  /*for(i = 0; i <10; i++)
  {
     b[i] = pointer[i];
  }*/
  for( i = 0;i<10;i++)
  {
    printf("%d\n",b[i]);
  }
}
int main()
{
    f();
    return 0;
}

输出结果:

0
1
2
3
4
5
6
7
8
9
输出结果改变了,验证了局部变量的地址是不可靠的。

程序中的堆

堆是程序中一块预留的内存空间,可由程序自由使用
堆中被程序申请使用的内存在被主动释放前将一直有效

如果一直申请堆空间,不释放,将会导致堆空间被申请完了,程序运行会越来越慢,最后导致无法运行。

为什么有了栈还需要堆?

栈上的数据在函数返回后就会被释放掉,无法传递到函数外部,如:局部数组

程序中的堆

C语言程序中通过库函数的调用获得堆空间
头文件:malloc.h
malloc 以字节的方式动态申请堆空间
free 将堆空间归还给系统
系统对堆空间的管理方式

1.空闲链表法 2.位图法 3.对象池法等等
int p = (int)malloc(sizeof(int)); //申请4字节

程序中的静态存储区

静态存储区随着程序的运行而分配空间
静态存储区的生命周期直到程序运行结束
在程序中编译期静态存储区的大小就已经确定
静态存储区主要用于保存全局变量和静态局部变量
静态存储区的信息最终会保存到可执行程序中

例子39-2:

#include "stdio.h"
int g_v = 1;
static int g_vs = 2;
void f()
{
    static int g_vl = 3;
    printf("%p\n",&g_vl);
}
int main()
{
    printf("%p\n",&g_v);
    printf("%p\n",&g_vs);
    f();
    return 0;
}

输出结果:

007E7000
007E7004
007E7008

小结:

栈,堆和静态存储区是程序中的三个基本数据区
栈区主要用于函数的调用和使用
堆主要用于内存的动态申请与归还
静态存储区用于保存全局变量和静态变量

YingLi
6 声望4 粉丝

From zero to hero.