C语言程序内存管理

2016/12/06 C 内存管理

C语言程序内存管理

最近在学习elf文件相关的知识,发现自己对这真是一窍不通,半路出家的坏处就体现出来。

在程序的运行的过程中,其所需要的内存并不是连续分布的,而是按照一些机制按需分配的。主要是按照堆(heap),栈(stack),BSS段,数据段,代码段

概述

BSS段

(Block Started by Symbol)BSS指用来存放程序中未初始化的全局变量的一块内存区域,属于静态内存分布

数据段(.data)

指存放程序中已初始化的全局变量的一块内存区域,属于静态内存分配。

代码段(.text)

通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于 只读 , 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些 只读的常数变量 ,例如字符串常量等。程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本.

堆(heap)

堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)

栈(stack)

栈又称堆栈, 存放程序的 局部变量 (但不包括static声明的变量, static 意味着 在数据段中 存放变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。储动态内存分配,需要程序员手工分配,手工释放

Typical memory arragement

上图是一个典型也是最简单的内存分布。

各段的区别

.bss与.data区别

.bss段属于未初始化数据,所以不会影响目标文件大小。.data段属于已初始化数据会影响目标文件大小。

int inBss[10000];
int inData[10000]={1,2,3};

上面两个声明,inBss数组的数据仅会在运行时初始化,而inData数组会在编译阶段初始化,然后load进RAM中,所以inData数组的大小会体现在程序文件大小中。

堆与栈的区别

堆与栈的区别

代码段(.text)

.text存放的是程序运行的代码,及一些只读常量,该处内存在一般情况下设计为只读区域,一般存放的是编译之后的机器码。

int cntWorkerBees=10;
char *str="God's own prototype";

mappingBinaryImage

int a = 0; //全局初始化区  
char *p1; //全局未初始化区  
main()  
{  
  int b; //栈  
  char s[] = "abc"; //栈  
  char *p2; //栈  
  char *p3 = "123456";// 123456\0在常量区,p3在栈上。  
  static int c =0 //全局(静态)初始化区  
  p1 = (char *)malloc(10);  
  p2 = (char *)malloc(20);  
  //分配得来得10和20字节的区域就在堆区。  
  strcpy(p1, "123456");// 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。  
}