C程序的内存分布

引子:linux

#include<stdio.h>
int main()
{ 
  char*p =”tiger”;
  p[1]=’I’;
  p++;
  printf(“%s\n”,p);
}

编译执行后提示:段错误
程序员

简单分析:数据结构

char *p ="tiger";  系统在栈上开辟了4个字节存储p的数值,其中"tiger"在只读存储区中存储,所以"tiger"的内容不能改变,*p="tiger",表示地址赋值,所以,p指向了只读存储区,所以改变p指向的内容会引发段错误。可是由于p自己内容是存放在栈上,所以p的数值是能够改变的,所以p++是正确的。函数

上述出现了栈、只读存储区 这些都是C程序中各个不一样存储部分的名称,了解了C程序的存储分布能够有效的下降coding过程出现段错误的概率。spa

C程序通过编译-连接-重定位后就会生成一个有二进制机器代码组成的可执行文件,通常有以下几个部分组成:
命令行

.text 代码段
code

CPU执行的机器指令部分。代码段一般是能够共享的,因此在运行时被多个进程使用也只需有一个副本,另外,正文段经常是只读的,以防止程序因为意外事故而修改其自身的指令。另外,代码段还规定了局部变量申请内存空间的信息进程

.data 数据段内存

程序中被初始化的全局变量,静态变量以及字符串常量(即上述所说的只读存储区)字符串

.bss 未初始化数据段

未初始化的全局或者静态变量放置于此。因为是未初始化,因此加载至内存后内核会将此段初始化为0

当程序加载至内存后有须要堆和栈来存放运行时存取的数据

堆 heap (动态存储区)

自下而上增加,通常有程序员本身分配(malloc)和释放(free),分配速度较慢,但因为是采用链式非连续地址的数据结构因此灵活度比较大,通常32bit系统下堆能够分配到4G内存,但容易产生内存碎片,关于则方面能够参考下linux的内存分配机制slab和buddy的有机结合

栈 stack

自顶向下增加,由系统自动分配,分配速度较快,因为是系统事先分配的连续地址内存会受限于OS预设的大小,超出即出现overflow,linux下可使用ulimit -a查看当前栈大小和-s 设置栈带下。再栈中保存着函数调用的环境变量,在进行函数调用时入栈顺序为:函数调用完后须要执行的语句-->函数调用参数,通常是从右向左入栈-->最后就是函数的局部变量,函数调用完后再依次出栈

C程序内存分布图:

++++++++++++++++++++++  高地址

命令行参数和环境变量

++++++++++++++++++++++

栈, 向下增加

++++++++++++++++++++++

堆,向上增加

++++++++++++++++++++++

bss段

++++++++++++++++++++++

data段

++++++++++++++++++++++

text段

++++++++++++++++++++++ 低地址

你们可使用objdump或者readelf来查看下ELF格式的程序中各个段的详细信息

相关文章
相关标签/搜索