6.内存的布局

来源:互联网 发布:mac osx 重装系统 编辑:程序博客网 时间:2024/06/06 02:04

内存布局

一块内存分为多个部分,分别存放不同的数据,它是与CPU进行沟通的桥梁。


一、内存布局概览



可以看到,一块内存由内核区、栈、堆、数据段、代码段以及用户不可访问区域组成,下面,重点介绍几个段。


二、内存区域

1、栈(Stack)

(1)存放的数据:

·主要用来存储进程执行过程中所产生的局部变量。

·为了可以实现函数的嵌套循环调用和返回,栈还必须包含函数切换时当下的代码地址和相关寄存器的值。

(2)说明:

栈也可以称为栈内存、堆栈(“堆栈”与“堆”没有任何关系),全称是“运行时栈”(Run-time Stack)。它严格按照“后进先出”的原则来操作,而这种后进先出的逻辑,就称为栈。栈会随着进程的运行而不断发生变化:一旦有新的函数被调用,就会立即分配一段内存,专门用于存放该函数的局部变量(包括形参),当函数执行完毕,所占用的栈内存会被立即释放。

栈中的环境变量和命令行参数在程序一开始运行时就被固定在了栈底(紧挨内核的地方),且进程在整个运行期间不再发生变化。如果进程运行时对环境变量作了更改,那么新的环境变量会被复制到堆中。


2、堆(Heap)

(1)堆内存操作的相关C函数:

①void *malloc(size_t size);------在堆中申请一块大小为size的连续内存。申请成功则返回新申请的内存的首地址,失败则返回NULL。

例:int *p = (int *)malloc(100); ==>申请一块100字节大小的连续空间。malloc不初始化,里边数据是随机的垃圾数据。

②void *calloc(size_t size);------在堆中申请n个大小为size的连续空间。(int *)malloc(100);

例:int *p = (int *)calloc(10, sizeof(int)); ==>申请了10个大小为int类型大小(4字节)的连续空间,并自动初始化为0。

③void *realloc(vod *ptr, size_t size);------改变堆中ptr的内存大小。申请成功则返回新的首地址(这个首地址发生了改变,可能与原首地址相同,也可能不同),失败则返回NULL。若size为0,相当于free(str);。

例:int *p = (int *)malloc(100);  p = realloc(p, 10); ==>将p指向的这块内存的原大小100字节改变为新的一块大小为10字节的内存。

④void free(void *ptr);------释放ptr所指向的内存。

例:int *p = (int *)malloc(100);   free(p); ==>释放掉malloc所申请的内存p,释放之后p就成了野指针。

(2)C++对堆内存的申请和释放:

①申请:new 

pointer = new type; // 申请一个type类型大小的空间pointer = new type(initializer); // 申请一个type类型大小的空间,并将pointer指向的值初始化为initialzerpointer = new type[size];  // 申请size个type类型大小的空间

new可以给数据类型分配一个新结点并返回一个指向新分配内存区的首地址.,也可以对它进行初始化,中括号中的 size 可以分配尺寸大小。

②释放:delete

delete p;delete[] pArray;
delete操作用来释放p指向的内存,这个指针先前应该被 new调用过。上面第二种形式用于删除一个数组。

(3)说明:

堆内存(简称“堆”)是一块自由内存,这个区域变量的定义和释放有用户决定。堆的最大值唯一限制于系统的物理内存大小。


3、数据段

(1)数据段存放的数据:

.bss段:未初始化的静态数据(它们都将被初始化为0)。

.data段:已初始化的静态数据(这个初始值从程序文件中赋值而来)。

.rodata段:常量(只读数据,比如进程中的字符串、字符常量、整型常量....)。

(2)说明:

数据段实际分为3个部分,地址从高到低分别是.bss段、.data段、.rodata段。数据段的大小在进程一开始就是固定的。静态数据指的是所有的全局变量以及static型局部变量。如果静态数据未被初始化,则程序开始运行时系统将会自动将它们初始化为0后放在.bss段中,因此在程序文件中就没有保存未初始化的变量的值了。

4、代码段

(1)代码段存放的数据:

.text段:存放用户程序代码。

.init段:存储系统给每一个可执行程序自动添加的“初始化”代码。

(2)说明:

实际上代码段至少分为两部分:.text段和.init段。

.text段也称为正文段,.text是一个默认的名称,它囊括了用户定义的所有函数代码。当然,我们也可以将某些指定的函数放到自己指定的段中。

.init段代码的功能是:环境变量的准备、命令行参数的组织和传递等,产生的这部份数据被放在栈底。




原创粉丝点击