我们写过很多c/c++代码(或者其他编程语言),然后通过编译器进行编译再运行一个程序,要使用数据对象(例如变量、类对象)是得要分配内存的,而大家可能不太熟悉这些数据对象是如何分配的。那么接下来,笔者为大家逐步分析并解决这些疑惑。
我们写完代码,通过编译器进行编译之后,C/c++程序便生成了二进制映像文件(也称为目标文件(c++里面是.obj),是按照可执行文件(c++中的.exe)格式存储的,但不是真正意义上的可执行文件,目标文件只是还没有通过链接装载的过程),这文件的组成成分包含:栈区,堆区,数据段(已经初始化读写数据段、只读数据段、BSS段(未初始化数据段))和代码段。(程序没有运行的时候,这二进制映像文件暂时存放在硬盘当中的;当程序被打开的时候,根据文件的需要,每个区域映射到系统分配相应的内存当中)
二进制映像文件分配区域和程序运行时分配内存的图解:
在操作系统中,一个进程就是处于执行期的程序(当然包括系统资源),实际上是正在执行的程序代码的活标本。那么进程的逻辑地址空间是如何划分的呢?
以下是程序运行时,二进制映像文件映射到内存的图解:
(此图出自某网友的一篇文章)
(左边的是UNIX/LINUX系统的执行文件,右边是对应进程逻辑地址空间的划分情况。)
动态存储方式
意义:所谓动态存储方式是指在程序运行期间根据需要进行动态的分配存储空间的方式。
动态存储变量是在程序执行过程中,使用它时才分配存储单元, 使用完毕立即释放。
典型的例子是函数的形式参数,在函数定义时并不给形参分配存储单元,只是在函数被调用时,才予以分配,调用函数完毕立即释放。如果一个函数被多次调用,则反复地分配、释放形参变量的存储单元。
1.栈区(stack):
==程序运行时,负责栈区的操作者:操作系统
由系统自动分配释放
==存储的数据:
1.函数的形参变量
2.自动变量(auto register):函数的普通局部变量,不包括静态局部变量
3.函数调用现场保护和返回地址等。
==特征:其操作方式类似于数据结构中的栈。
==组成部分:
在栈区里面其实又可以分成好几个区域,他们叫做栈桢,一个栈桢就是一个函数,需要调用该函数的时候就如入栈,函数return的时候就会弹出栈,所以他们的生命周期是从函数的开始直到函数结束。
而栈帧里面又存放着什么呢,栈帧存放着以下几种东西:参数变量的地址,局部变量的地址,return的地址、栈指针和基指针等。
==产生栈区的目的:作为暂时存储器,因为频繁调用一些函数,存储的变量会频繁分配又释放,不会长期占有内存。