C语言程序内存管理
最近在学习elf文件相关的知识,发现自己对这真是一窍不通,半路出家的坏处就体现出来。
在程序的运行的过程中,其所需要的内存并不是连续分布的,而是按照一些机制按需分配的。主要是按照堆(heap),栈(stack),BSS段,数据段,代码段
概述
BSS段
(Block Started by Symbol)BSS指用来存放程序中未初始化的全局变量的一块内存区域,属于静态内存分布
数据段(.data)
指存放程序中已初始化的全局变量的一块内存区域,属于静态内存分配。
代码段(.text)
通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于 只读 , 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些 只读的常数变量 ,例如字符串常量等。程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本.
堆(heap)
堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)
栈(stack)
栈又称堆栈, 存放程序的 局部变量 (但不包括static声明的变量, static 意味着 在数据段中 存放变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。储动态内存分配,需要程序员手工分配,手工释放
上图是一个典型也是最简单的内存分布。
各段的区别
.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";
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"优化成一个地方。
}