笔记:程序内存管理 .bss .data .rodata .text stack heap

1.未初始化的全局变量(.bss段)

bss段用来存放 没有被初始化已经被初始化为0 的全局变量。如下例代码:

#include<stdio.h>

int bss_array[1024*1024];
int main(int argc, char *argv[])
{
    return 0;
}

编译并查看:

$ gcc -g mainbss.c -o mainbss
$ ls -l mainbss
-rwxrwxr-x. 1 hy hy 8330 Apr 22 19:33 mainbss
$ objdump -h mainbss |grep bss
mainbss:     file format elf32-i386
 24 .bss          00400020  0804a020  0804a020  00001018  2**5
$ size mainbss
   text	   data	    bss	    dec	    hex	filename
   1055	    272	4194336	4195663	 40054f	mainbss

全局变量bss_array的大小为4MB = 1024*1024*sizeof(int) Byte = 4194304 Byte。 通过size 查看可知数据被存在了 bss 段

  而 可执行文件mainbss 有8KB左右。可知,bss类型的全局变量只占用 运行时的内存空间,而不占用可执行文件自身的文件空间

2. 已被初始化为非零的全局变量(.data段)

  data段用来存放已经被初始化为非零的全局变量。如下代码,只将矩阵的第一个元素初试化为1:

#include<stdio.h>

int data_array[1024*1024]={1};
int main(int argc, char *argv[])
{
    return 0;
}

编译查看

[[email protected] memcfg]$ gcc -g maindata.c -o maindata
[[email protected] memcfg]$ ls -l maindata
-rwxrwxr-x. 1 hy hy 4202682 Apr 22 19:48 maindata
[[email protected] memcfg]$ objdump -h maindata |grep \\.data
 23 .data         00400020  0804a020  0804a020  00001020  2**5
[[email protected] memcfg]$ size maindata
   text	   data	    bss	    dec	    hex	filename
   1055	4194604	      4	4195663	 40054f	maindata

而 可执行文件maindata 有4MB左右。通过size 查看可知数据被存在了 data 段

可知,data类型的全局变量既占用运行时的内存空间,也占用可执行文件自身的文件空间

3.常量数据(.rodata段)

1)rodata用来存放常量数据。 ro: read only

2)字符串会被编译器自动放在rodata中,加 const 关键字的常量数据会被放在 rodata 中

3)在有的嵌入式系统中, rodata放在 ROM(或 NOR Flash)里,运行时直接读取,不须加载到RAM内存中。

所以,在嵌入式开发中,常将已知的常量系数,表格数据等造表加以 const 关键字。存在ROM中,避免占用RAM空间。

4.代码(.text段)

  text段存放代码(如:函数)和部分整数常量(应该指的是一些立即数),这个段是可执行的。

5.栈(stack)

  1)stack 存放函数的局部变量和函数参数

  2)被调用函数的参数和返回值 被存储到当前程序的栈区,之后被调用函数再为自身的自动变量和临时变量在栈区上分配空间

  3)函数返回时,栈区的数据会被释放掉,先入后出(FILO)的顺序。

6.堆(heap)

  heap用来动态分配内存,由程序自身决定开辟和释放。

6.1 malloc/free

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char *argv[])
{
    int *p = (int *)malloc(10*1);
    // p= (int *)malloc(10*1);
    if(p==NULL) {
        printf("malloc p err\n");
        return -1;
    }
    free(p);
    printf("p = %4x\n",p);
    p = NULL;
    printf("p = %4x\n",p);
    return 0;
}

程序运行结果:

[[email protected] memcfg]$ gcc maindata.c
[[email protected] memcfg]$ ./a.out
p = 9cf4008
p =    0

1)开辟了空间,就要适时的释放。释放时,指针应指向开辟时的内存空间,所以在使用指针时,要注意不要修改了其地址,或者将开辟时的起始地址保存起来。

2)对指针free后,其地址不一定就为NULL。如代码中的 p,在 free(p)后,printf(p)后并非为0。所以建议在free(p)后,立即加一句p=NULL。

3)检查p的地址 if(p!=NULL){ ... }

6.2 calloc/realloc

1)calloc()函数

void *calloc(size_t nmemb, size_t size);

  参数nmemb 表示要分配元素的个数,size表示每个元素的大小,分频的内存空间大小是 nmemb*size; 返回值是 void* 类型的指针,指向分配好的内存首地址。

用法一:分配1024*sizeof(int)字节大小的内存,并清空为0

int *p = (int *)calloc(1024,sizeof(int));

用法二:与 alloc等价的 malloc 用法

int *p = (int *)malloc(1024*sizeof(int));
memset(p,0,1024*sizeof(int));

差异:用法一,会根据分配的的类型来初始化为0,如:分配int型,则初始化为(int)0; 若为指针类型,则初始化为空指针;若为浮点,则初始化为浮点型。

    用法二,不成保证初试化为空指针值和浮点型。(与NULL常量和浮点型的定义有关)

2)realloc()函数

  realloc()用来重新分配正在使用的一块内存大小。

定义:

void *realloc(void *ptr, size_t size);

用法示例:

int *p = (int *)malloc(1024);    //
p = (int *)realloc(512);        // 重新分配为 512字节大小内存,缩小数据丢失
p = (int *)realloc(2048);      // 重新分配为2048字节大小内存

注意:经过realloc()调整后的内存空间起始地址有可能与原来的不同。

摘录书籍

《ARM嵌入式Linux系统开发详解》 弓雷 等编著

《高质量嵌入式Linux C编程》 梁庚 等编著

时间: 2024-08-26 05:07:12

笔记:程序内存管理 .bss .data .rodata .text stack heap的相关文章

Linux System Programming 学习笔记(九) 内存管理

1. 进程地址空间 Linux中,进程并不是直接操作物理内存地址,而是每个进程关联一个虚拟地址空间 内存页是memory management unit (MMU) 可以管理的最小地址单元 机器的体系结构决定了内存页大小,32位系统通常是 4KB, 64位系统通常是 8KB 内存页分为 valid or invalid: A valid page is associated with an actual page of data,例如RAM或者磁盘上的文件 An invalid page is

《30天自制操作系统》笔记(07)——内存管理

<30天自制操作系统>笔记(07)--内存管理 进度回顾 上一篇中处理掉了绝大部分与CPU配置相关的东西.本篇介绍内存管理的思路和算法. 现在想想,从软件工程师的角度看,CPU也只是一个软件而已:它的功能就是加载指令.执行指令和响应中断,而响应中断也是在加载指令.执行指令.就像火车沿着一条环形铁轨前进:当中断发生时,就好像铁轨岔口处变轨了,火车就顺着另一条轨迹走了:走完之后又绕回来重新开始.决定CPU是否变轨的,就是CPU里的特定寄存器. 这是题外话,就此为止. 什么是内存管理 假设内存大小是

操作系统概念学习笔记 15 内存管理(一)

操作系统概念学习笔记 15 内存管理(一) 背景 内存是现代计算机运行的中心.内存有很大一组字或字节组成,每个字或字节都有它们自己的地址.CPU根据程序计数器(PC)的值从内存中提取指令,这些指令可能会引起进一步对特定内存地址的读取和写入. 一个典型指令执行周期,首先从内存中读取指令.接着该指令被解码,且可能需要从内存中读取操作数.在指令对操作数执行后,其结果可能被存回到内存.内存单元只看到地址流,而并不直到这些地址是如何产生的(由指令计数器.索引.间接寻址.实地址等)或它们是什么地址(指令或数

操作系统概念学习笔记 16 内存管理(二) 段页

操作系统概念学习笔记 16 内存管理 (二) 分页(paging) 分页(paging)内存管理方案允许进程的物理地址空间可以使非连续的.分页避免了将不同大小的内存块匹配到交换空间上(前面叙述的内存管理方案都有这个问题,当位于内存中的代码和数据需要换出时,必须现在备份存储上找到空间,这是问题就产生了.备份存储也有前面所述的与内存相关的碎片问题,只不过访问更慢). 传统上,分页支持一直是由硬件来处理的.最近的设计是通过将硬件和操作系统相配合来实现分页. 基本方法 实现分页的基本方法设计将物理内存分

《python源码剖析》笔记 pythonm内存管理机制

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.内存管理架构 Python的内存管理机制都有两套实现:debug模式和release模式 Python内存管理机制的层次结构: 图16-1 第0层是操作系统提供的内存管理接口,如malloc.free 第1层是Python基于第0层操作系统的内存管理接口包装而成的,主要是为了处理与平台相关的内存分配行为. 实现是一组以PyMem_为前缀的函数族 两套接口:函数和宏. 宏,可以避免函数调

linux kernel学习笔记-5内存管理(转)

http://blog.sina.com.cn/s/blog_65373f1401019dtz.htmllinux kernel学习笔记-5 内存管理1. 相关的数据结构 相比用户空间而言,在内核中分配内存往往受到更多的限制,比如内核中很多情况下不能睡眠,此外处理内存分配失败也不像用户空间那么容易.内核使用了页和区两种数据结构来管理内存: 1.1 页 内核把物理页作为内存管理的基本单位.尽管CPU的最小可寻址单位通常为字(甚至字节),但是MMU(内存管理单元,管理内存并把虚拟地址转换为物理地址的

黑马程序员_IOS开发_Objective-C学习笔记_内存管理

1.内存管理概述 1.1什么是内存管理:内存管理是程序设计中常用的资源管理的一部分,每个计算机系统可供程序使用的内存都是有限的. 1.2为什么要使用内存管理:当我们的程序运行结束的时候,操作系统将回收其我们程序占用内存.但是,只要程序还在运行,它就会一直占用内存.如果不进行及时清理不用的内存,内存最终将被耗尽.每个程序都会使用内存,我们必须确保在需要的时候分配内存,而在程序运行结束时释放占用的内存.如果我们只分配而不释放内存,将发生内存泄漏. 1.3引用计数:1.3.1只有当你对一个对象了all

C程序内存管理

C程序的内存管理 熟悉Java语言的肯定知道,Java中内存管理是由虚拟机帮助我们完成的,在C/C++中可不是这样,程序员需要自己去分配和回收内存空间.本文记录了C程序在内存中存储结构.C变量和函数常见的存储类型.分配和回收内存等方面的内容.以下C程序所使用的编译器版本是GCC 4.4.7. 从一个C程序说起 文件的结构 对于以下这段Hello.c程序再熟悉不过了 #include<stdio.h> int main(void) { printf("Hello World\n&quo

Magenta源代码笔记(3) —— 内存管理【转】

转自:http://blog.csdn.net/boymax2/article/details/52550197 版权声明:本文为博主原创文章,未经博主允许不得转载. Magenta内核支持虚拟地址的配置,依赖于cpu内的mmu模块. 下面会从以下几个方面对Magenta内核内存管理方面的代码进行分析: 1.mmu初始化,也就是硬件mmu的初始化,以底层寄存器操作为主,汇编 2.pmm初始化,也就是代码中物理内存结构的初始化 3.vmm初始化,也就是代码中虚拟内存结构的初始化 mmu初始化 mm