汉扬编程 C语言入门 C语言内存简析,堆栈的使用

C语言内存简析,堆栈的使用

持续分享嵌入式技术,操作系统,算法,c语言/python等,欢迎小友关注支持

内存分配32位操作系统支持4GB内存的连续访问,但通常把内存分为两个2GB的空间,每个进程在运行时最大可以使用2GB的私有内存(0x00000000—0x7FFFFFFF)。

至于高端的2GB内存地址(0x80000000—0xFFFFFFFF),操作系统一般内部保留使用,即供操作系统内核代码使用。

每个进程都能看到自己的2GB内存以及系统的2GB内存,但是不同进程之间是无法彼此看到对方的。

虚拟内存 虚拟内存的基本思想是:用廉价但缓慢的磁盘来扩充快速却昂贵的内存。

所有进程共享机器的物理内存,当内存使用完时就用磁盘保存数据。在进程运行时,数据在磁盘和内存之间来回移动。

在进程执行过程中,操作系统负责具体细节,使每个进程都以为自己拥有整个地址空间的独家访问权。这个幻觉是通过“虚拟内存”实现的。

内存管理硬件负责把虚拟地址翻译为物理地址,并让一个进程始终运行于系统的真正内存中,应用程序员只看到虚拟地址,并不知道自己的进程在磁盘与内存之间来回切换。

内存的使用栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈。堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。全局区(又叫静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。常量区(又叫文字常量区):常量字符串就放在这里。程序结束后由系统释放。程序代码区:存放函数体的二进制代码。(请注意是函数体) 有时候对一个进程的内存空间在逻辑上也可简单地划分为三个部分:代码区、静态数据区和动态数据区。

动态数据区一般就是“堆栈”。“栈”和“堆”虽然都属于动态数据区,但却是不同的东西。

栈是一种线性结构,而堆是一种链式结构。

进程中的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰的。堆和栈可以分别通过“基地址”和“栈顶”地址来描述。

关于堆的创建方式,大家可以看一下相关的C语言书籍,内容也通俗易懂,这里不再一一介绍

来看一个网上很流行的经典例子:

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 *)mall0c(20); 堆 } 堆栈的相关特性栈: 在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。 当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。

堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

堆内存在申请的时候会产生内存碎片,空闲内存碎片存在的方式有两种:内部碎片 ,外部碎片 。

内部碎片的产生:

因为所有的内存分配必须起始于可被 4、8 或 16 整除(视处理器体系结构而定)的地址或者因为MMU的分页机制的限制,决定内存分配算法仅能把预定大小的内存块分配给客户。

假设当某个客户请求一个 43 字节的内存块时,因为没有适合大小的内存,所以它可能会获得 44字节、48字节等稍大一点的字节,因此由所需大小四舍五入而产生的多余空间就叫内部碎片。

外部碎片的产生:

频繁的分配与回收物理页面会导致大量的、连续且小的页面块夹杂在已分配的页面中间,就会产生外部碎片。

假设有一块一共有100个单位的连续空闲内存空间,范围是0~99。如果你从中申请一块内存,如10个单位,那么申请出来的内存块就为0~9区间。

这时候你继续申请一块内存,比如说5个单位大,第二块得到的内存块就应该为10~14区间。

如果你把第一块内存块释放,然后再申请一块大于10个单位的内存块,比如说20个单位。

因为刚被释放的内存块不能满足新的请求,所以只能从15开始分配出20个单位的内存块。现在整个内存空间的状态是0~9空闲,10~14被占用,15~24被占用,25~99空闲。其中0~9就是一个内存碎片了。

如果10~14一直被占用,而以后申请的空间都大于10个单位,那么0~9就永远用不上了,变成外部碎片。

本文来自网络,不代表汉扬编程立场,转载请注明出处:http://www.hyzlch.com/cjia/6128.html

C语言这么难,为何大家都如飞蛾扑火般学习?现在带你揭秘

单片机控制交流电机正反转的C语言程序,暂停怎么办

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

返回顶部