关于内存的段式管理

来源:互联网 发布:淘宝批量上传淘宝联盟 编辑:程序博客网 时间:2024/05/17 08:55

平时写代码只顾现象,不怎么注意底层原理原理,打算写几篇介绍底层的博文。
开始想写这篇博文是因为一个小小的C语言问题:

    char* p = "hello world";    char p[12] = {"hello world"};

为什么第一个p指向的内容不可变,而第二个p指向的内容是可变的呢?
首先我们来了解一下计算机中内存的管理方式。
传统的内存管理方式为 段式管理 操作系统按照存储数据的不同,将内存划分为6个段:

. text(代码段)

既然是代码段,都是将要执行的指令,不能修改,所以是只读的。

  • 存储数据:
    编译好的可执行代码
  • 备注:
    由PC指针由上到下顺序执行,遇中断会暂存当前指令地址,跳转到中断片执行,之后再跳转回暂存指令。

.data(数据段)

.data直观上看就是存放数据的地方

  • 存储数据:
    静态变量(由static定义的变量),以及全局变量(初始化后)

.bss(bss段)

bss的全称是block started by symbol直译过来就是从符号开始的块,实际上是源于旧式IBM电脑上的指令名

  • 存储数据:
    全局变量(未初始化的)

  • 备注:
    为了节省空间,只记录bss段的大小并不记录bss段里存放变量大小,所以未初始化的全局变量都为0

.rodata(常量区)

ro就是read only 连起来就是只读数据,只读的数据当然就是常量了

  • 存储数据:
    宏定义的数值数值常量字符串常量,及const定义数据

.stack(栈区)

在计算机中栈区的大小远远小于堆区(大概是几m),所以定义一个很大的数组时可能会出现堆栈溢出的现象。

  • 存储数据:
    auto变量(由操作系统自动分配的变量),或者说局部变量,和数组

  • 备注:
    通过sp与fp指针分配和释放空间
    C语言中没有数组,只有英文字符,数字,标点符号和关键字

.heap(堆区)

堆区表头存放着每块空闲区域的大小和位置,当申请空间时会顺序遍历表头寻找大小合适的空闲区域(一般会找到比申请空间大的区域),然后将这块空间地址从表头删除,将剩余空间地址存入表头

  • 存储数据:
    由程序员自行分配释放的数据

  • 备注:
    使用malloc(),free()newdelet 申请获释放的数据,但是地址存放的指针变量的还是存放在栈区中的
    堆区空间在内存中以链表形式排列,表头存储着每块空闲区域的大小和位置,每一个节点头部存储着节点大小

这里写图片描述

  • 备注
    内存的分配方式有操作系统决定

在linux中使用size可以查看所写代码在每段各占大小
这里写图片描述

使用ulimit -s可以查看当前可使用栈区大小
这里写图片描述

现在我们来分析开始的小问题
char* p = "hello world";

其中p存放在栈区,而字符串在程序运行前加载到了内存的数据段(也可以叫常量区)所以不能更改。

char p[12]={""hello world};

而这行代码在定义了一个指针变量p,并在栈区申请了12个char形空间,并将首地址赋给了指针变量p。

第一次发博文,如果写的有问题,或者是有什么可以改进的地方请多多指教。

谁知道如何打出emoji。。。。

1 0
原创粉丝点击