今天老师讲了C语言中的内存布局情况特地记录下来
C程序程序空间布局
1)、正文段:也可称为代码段或代码节,该段特点如下:
·此段为共享段;
·运行时,内存会复制一份该段的副本;
·为只读,目的是为了方式意外情况将代码修改而导致程序出错;
2)、数据段:数据段包含如下3个节
a)、ro.data:常量数据节,该节特点如下:
·存放常量数据,如printf(“%s%d”, xx, xx);和char *p = “hello”中的常量字符串就 存在了该数据节中;
·为只读;
b)、.data:数据节,该节特点如下:
·专门用于存放初始化了的静态变量。当可执行文件在磁盘上时,这个节是要开出开
出空间来存放用于初始化的常量数值的;
·为可读可写;
c)、.bss:也是一个数据节,其特点如下:
·存放未初始化了的静态变量。当可执行文件在磁盘上时,这个节是没有开出变量空 间的,因为没有设置初始化常量数据,这里只有一些占位符起说明所用,当程序运行
起来后,在内存中会为该节开出空间,并且会全部清0;
·为可读可写;
其它段或节:如果我们的程序是在操作系统上运行的话,还用该有其它的段或节,目的
是为了辅我们的c程序在操作系统上运行起来。
实验:(用linux中的size命令来查看)。
先看看数据段:
#include <stdio.h>
int main(void)
{
return 0;
}
#include <stdio.h>
int arr[1000];
int main(void)
{
return 0;
}
data段增加了4024字节
#include <stdio.h>
int arr[1000]={1};
int main(void)
{
return 0;
}
bss段增加了4028!
(3) 栈
由编译器自动分配释放管理。局部变量及每次函数调用时返回地址、以及调用者的环境信息(例如某些机器寄存器)都存放在栈中。新被调用的函数在栈上为其自动和临时变量分配存储空间。通过以这种方式使用栈,C函数可以递归调用。递归函数每次调用自身时,就使用一个新的栈帧,因此一个函数调用实例中的变量集不会影响另一个函数调用实例中的变量。
a.局部变量
b.函数调用时返回地址
c.调用者的环境信息(例如某些机器寄存器)。
(4) 堆
需要由程序员分配释放管理,若程序员不释放,程序结束时可能由OS回收。通常在堆中进行动态存储分配。
如程序中的malloc, calloc, realloc等函数都从这里面分配。堆是从下向上分配的。
虚拟内存空间的布局
虚拟内存空间的布局在结构上基本与我们前面讲的c程序的结构一致。
如下图:
从上图我们看到,虚拟内存空间的大小是4G(虚拟地址从0到4G-1)。
·应用空间:0~3G,用于运行应用代码,其中0~0x08048000之间的空间未用。
·内核空间:3~4G,用于运行系统调用函数的内核级的代码。
这两部分空间是有权限差别的,应用空间不可以访问内核空间,但是反过来在遵循某些条件的情况下,内核空间是可以访问应用空间的。
·代码段:只包含.text
·数据段:包括ro.data,.data,.bss,堆和栈
·静态数据区:包含.text,.ro.data,.data,.bss,静态数据区的空间分配是由编译的时候
决定的,运行时不可以在静态去开空间,也不可以将静态区中已开出的空间释放。
·动态数据区:包含栈和堆
栈:自动区,栈中空间在程序运行时,自动的开出和自动释放。
堆:手动区,堆中空间在程序运行时,手动开出(malloc等函数)和手动的释放(free 函数),如果程序结束时没有释放开出的空间的话,这些空间会被一直占用,导 致内存泄露,直到机器从新启动后,这些堆中的空间才会被释放。
·只读段:包含.text.,ro.data
·可读可写段:包含.data,.bss,堆,栈