天天看点

虚拟地址空间布局

在多任务系统中,每个进程都运行在自己的虚拟地址空间上,32为模式下它是一个4G的内存地址块,在Linux系统下主要分为1G内核空间和3G用户空间,而在Windows系统下,内核空间和用户空间的划分比例为2:2.

在Linux系统下虚拟地址空间布局如下图所示:

虚拟地址空间布局

位于虚拟地址空间最低部分为保留区,未赋予物理地址

.text 为代码段用来存放程序执行代码

.data段称为数据段,用来存放程序中已初始化并且初始化不为0的全局变量和静态局部变量,数据段属于静态内存分配,可读可写

.bss段又称未初始化段,用来存放未初始化或者初始化为0的全局变量和静态局部变量

  数据段与BSS段的区别如下: 

     1) BSS段不占用物理文件尺寸,但占用内存空间;数据段占用物理文件,也占用内存空间。

     对于大型数组如int ar0[10000] = {1, 2, 3, ...}和int ar1[10000],ar1放在BSS段,只记录共有10000*4个字节需要初始化为0,而不是像ar0那样记录每个数据1、2、3...,此时BSS为目标文件所节省的磁盘空间相当可观。

     2) 当程序读取数据段的数据时,系统会出发缺页故障,从而分配相应的物理内存;当程序读取BSS段的数据时,内核会将其转到一个全零页面,不会发生缺页故障,也不会为其分配相应的物理内存。

     运行时数据段和BSS段的整个区段通常称为数据区。某些资料中“数据段”指代数据段 + BSS段 + 堆。

.heap段用于存放进程运行时动态分配的内存段,可动态扩张或缩减。堆中内容是匿名的,不能按名字直接访问,只能通过指针间接访问。当进程调用malloc(C)/new(C++)等函数分配内存时,新分配的内存动态添加到堆上(扩张);当调用free(C)/delete(C++)等函数释放内存时,被释放的内存从堆中剔除(缩减) 。

.stack又称堆栈,由编译器自动分配释放,行为类似数据结构中的栈(先进后出)

主要有三个用途:

(1)为函数内部声明的非静态局部变量提供存储空间

(2)记录函数调用过程中相关的维护性信息

(3)临时存储区,用于暂存长算式表达式部分计算结果或alloca()函数分配的栈内内存

Linux中可以用ulimit -s命令来查看和设置堆栈最大值,

函数堆栈调用开栈过程:

(1).压入实参  自右向左

(2).压下一行指令地址

(3).压调用方函数的栈底地址

(4).跳转到被调用方函数的栈帧

(5).开辟被调用方函数运行需要的栈空间

调用约定

_cdecl       c标准调用约定

_stdcall      windows下标准调用约定

_fastcall     快速调用约定

_thiscall     类成员方法调用约定

各约定不同点:

1.函数的符号生成

2.实参的入栈顺序

3.形参的开辟和清理

   _cdecl   调用方  调用方

   _stdcall  调用方  被调用方

_fastcall  调用方  被调用方

c++

继续阅读