您的位置:首页 > 编程语言 > C语言/C++

【C语言复习(二十四)】C语言程序内存结构总结

2014-06-23 11:00 169 查看
详细资料请参考:

【C语言复习(二十一)】C语言程序的存储区域

【C语言复习(二十二)】C语言程序的内存段

【C语言复习(二十三)】C语言程序中段的使用

根据前三篇文章的介绍,这里做一个简单的总结

1、三国天下

一个C语言程序在运行时,内存结构分为:全局静态区、动态区;动态区又包括:堆区、栈区;

全局静态区:程序运行过程中始终存在,运行结束后由操作系统释放,全局静态区里的大部分内存段在编译链接后产生,只有一个例外,是在程序初始化时开辟;

动态区:

程序运行过程中,由程序动态分配和释放的区域;

堆区:使用malloc函数申请的空间位于此内存区,使用后需要调用free函数释放,否则发生内存泄露等问题;

栈区:程序函数内部中使用的变量、函数的参数、函数的返回值将存储在此内存区,由编译器自动分配和释放;

全局静态区:

全局静态区又分为:只读数据区、读写数据区

只读数据区又分为:代码段、只读数据段

只读数据段:只读全局量、只读局部量、程序中使用的常量

读写数据区:已初始化数据段、未初始化数据段

已初始化数据段:已初始化全局(静态)变量、已初始化局部静态变量



2、程序中的栈区

栈中保存了一个函数调用所需的所有维护信息

函数参数、函数返回值

局部变量

函数调用上下文

如图:



在整个程序运行期间,首先进入main函数,然后调用其他函数时,程序的运行流程转出,并依次开辟如图的栈空间,因为调用完函数后还需返回原位置继续执行main函数,因此会记录返回地址,ebp为基址指针,它保存的值是上一个ebp的值,整个被调用的函数所需栈空间分配完成后,栈顶指针esp会指向栈顶,被调用函数运行结束后,栈顶指针会返回刚刚调用函数的流程转出处,这就依赖于ebp指针向前读取一个字节,然后赋给esp,这样栈顶就回到流程转出处了,接着ebp读取old ebp的值,返回上一个函数的ebp位置,这样一个函数调用流程结束。

3、程序中的堆

栈上的数据在函数调用返回后就会被释放掉,无法传递到函数外部,如:函数局部变量,因此才有了堆

堆是程序运行时一块巨大的内存空间,可由程序自由使用;

堆中被程序申请使用的内存在程序主动释放前将一直有效;

堆空间的使用需要申请,使用完后应该及时释放;

4、系统对堆空间的管理方式

基本的管理方式大概有:空闲链表法,位图法,对象池法等等

这里仅仅简单介绍一下空闲链表法:



比如当前想要申请一个4直接的空间,然后系统会根据链表去查询哪一个空间比较符合4字节,这里查找到了一个5字节的空间,然后系统就会把这个空间的起始地址返回给程序,这就是为什么有时候申请的堆空间比我们想要的大一点的原因。

5、静态存储区

程序静态存储区随着程序的运行而分配空间,直到程序运行结束;

在程序的编译期静态存储区的大小就已经确定;

程序的静态存储区主要用于保存程序中的全局变量和静态变量;

与堆和栈不同,静态存储区的信息最终会保存到可执行程序中;

6、小结

堆、栈和静态存储区是C语言程序涉及的三个基本存储区;

栈区主要用于函数调用的使用;

堆区主要是用于内存的动态申请和归还;

静态存储区用于保存全局变量和静态变量;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: