C语言里的内存分配以及堆栈的理解

        关于C里的内存分配问题,网上版本不一,个人总结了一下,有问题请指正。

        内存从上到下最开始是栈区:总是说堆栈,但堆和栈是两个完全不同的结构,栈区的数据存储与别的区不同是由上到下存储的,最开始进栈的地址最高,依次向下递减。栈区存储的主要是局部变量,它具有先进后出的特性,最先进来的数据要到最后才能取出来,我们在函数调用的时候,第一个进栈的是调用函数里被调用函数的下一条语句的初始地址,然后是调用函数的形式参数(函数调用的实参会被计算机存储在形式参数的存储区里),然后是函数里的各个局部变量,静态局部变量不入栈,它会存储在数据区(之后讲),在该函数执行结束的时候,再依次将局部变量,形式参数全部释放掉,这是栈的指针指向的是当初第一个进栈的调用函数的下一条语句,函数会继续从此继续执行。alloca()函数用来在栈中分配size个字节的内存空间,因此函数返回时会自动释放掉空间。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

       栈区下方是堆区。不同于栈区的内存分配是静态分配方式,即由计算机自动分配的,程序员无需过问,系统会自动为每一个值分配一个空间,而堆区是动态分配方式,即为了代码灵活性,由程序员自己设定的存储区。另一点不同于栈区的是,栈区像一个箱子,第一个放进去的要等到它上面的全部移走才能出来,而堆区像一个书架,虽然数据量也很大,但是可以随意放置并拿出自己想要的那本书。堆区分配地址用函数p=malloc (byte),返回值为分配的内存首地址 ,首先要知道操作系统有一个记录堆区空闲内存地址的链表,当程序员用malloc(byte)发出这个内存申请时,系统会根据这个链表,寻找第一个连续空闲内存大于byte的堆节点,并将这个堆节点从链表上删除。由于往往寻找到的空闲内存大小是大于byte的,系统还要将多余的那部分空闲内存的堆节点记录到链表中,因此用堆分配内存速度比较慢,而且容易产生大量的碎片,但是很灵活方便。一般分配好内存之后要用memset函数将该内存里的数据重新赋值,用 法: void *memset(void *p, char ch, unsigned n),将p指向的内存从上到下共n个字节赋值为ch,一般可赋值为0.注意内存使用结束之后要用free(p)将该内存释放掉,否则可能造成内存泄漏,一部分的内存没有被使用,但是由于没有free,因此系统认为这部分内存还在使用,造成不断的向系统申请内存,使得系统可用内存不断减少.但是,内存泄漏仅仅指程序在运行时,程序退出时,OS将回收所有的资源.可以重启一下程序。

      堆区下方是数据段。包括BBS(全局未初始化数据)以及全局变量/静态局部变量/常量数据(字符串)。由于这些数据在整个程序运行期间都可能用到,所以单独拿出来。

      最下方是代码段。即存放函数体的二进制代码。

      来看一个网上很流行的经典例子:
main.cpp 
  int a = 0; 全局初始化区 
  char *p1; 全局未初始化区 
  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);  堆

       free(p1);

free(p2);

  } 


评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值