深入C语言内存区域分配(进程的各个段)详解

转载 2015年11月19日 23:03:46

一般情况下,一个可执行二进制程序(更确切的说,在Linux操作系统下为一个进程单元,在UC/OSII中被称为任务)在存储(没有调入到内存运行)时拥有3个部分,分别是代码段(text)、数据段(data)和BSS段。这3个部分一起组成了该可执行程序的文件

C语言可执行代码结构

名称 内容
代码段 可执行代码、字符串常量
数据段 已初始化全局变量、已初始化全局静态变量、局部静态变量、常量数据
BSS段 未初始化全局变量,未初始化全局静态变量
局部变量、函数参数
动态内存分配

(1)代码段(text segment):存放CPU执行的机器指令。通常代码段是可共享的,这使得需要频繁被执行的程序只需要在内存中拥有一份拷贝即可。代码段也通常是只读的,这样可以防止其他程序意外地修改其指令。另外,代码段还规划了局部数据所申请的内存空间信息。

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

(2)数据段(data segment):或称全局初始化数据段/静态数据段(initialized data segment/data segment)。该段包含了在程序中明确被初始化的全局变量、静态变量(包括全局静态变量和局部静态变量)和常量数据。

(3)未初始化数据段:亦称BSS(Block Started by Symbol)。该段存入的是全局未初始化变量、静态未初始化变量。
而当程序被加载到内存单元时,则需要另外两个域:堆域和栈域。

(4)栈段(stack):存放函数的参数值、局部变量的值,以及在进行任务切换时存放当前任务的上下文内容。

(5)堆段(heap):用于动态内存分配,即使用malloc/free系列函数来管理的内存空间。
在将应用程序加载到内存空间执行时,操作系统负责代码段、数据段和BSS段的加载,并将在内存中为这些段分配空间。栈段亦由操作系统分配和管理,而不需要程序员显示地管理;堆段由程序员自己管理,即显示地申请和释放空间。

另外,可执行程序在运行时具有相应的程序属性。在有操作系统支持时,这些属性页由操作系统管理和维护。


下面给出示例程序代码,注释已经在代码中写明:



/*代码段、数据段和BSS段存储变量类型*/
#include <stdio.h>
const int    g_A       = 10;            //数据段
int            g_B       = 20;            //数据段
static int    g_C       = 30;            //数据段
static int    g_D;                    //BSS段
int            g_E;                    //BSS段
char        *p1;                    //BSS段
void main( )
{
    int           local_A;            //栈
    static int    local_C = 0;        //数据段
    static int    local_D;            //数据段


    char        *p3 = "123456";     //123456在代码段,p3在栈上
    p1 = (char *)malloc( 10 );      //堆,分配得来得10字节的区域在堆区
    strcpy( p1, "123456" );         //123456{post.content}放在常量区,编译器可能会将它与p3所指向 的"123456"优化成一块
    printf("\n");
    printf( "代码段,全局初始化变量, 只读const,  g_A,     addr:0x%08x\n", &g_A);
    printf("\n");
    printf( "数据段,全局变量,       初始化      g_B,     addr:0x%08x\n", &g_B);
    printf( "数据段,静态全局变量,   初始化,     g_C,     addr:0x%08x\n", &g_C);
    printf("\n");
    printf( "BSS段, 全局变量,       未初始化    g_E,     addr:0x%08x\n", &g_E, g_E );    
    printf( "BSS段, 静态全局变量,   未初始化,   g_D,     addr:0x%08x\n", &g_D );
    printf( "BSS段, 静态局部变量,   初始化,     local_C, addr:0x%08x\n", &local_C);
    printf( "BSS段, 静态局部变量,   未初始化,   local_D, addr:0x%08x\n", &local_D);
    printf("\n");
    printf( "栈,    局部变量,                   local_A, addr:0x%08x\n", &local_A );
    printf("\n");
    printf( "堆,    malloc分配内存,             p1,      addr:0x%08x\n", p1 );
}

C 语言内存区域分配(进程的各个段)详解

C语言可执行代码结构 名称内容代码段 可执行代码、字符串常量数据段 已初始化全局变量、已初始化全局静态变量、局部静态变量、常量数据BSS段 未初始化全局变量,未初始化全局静态变量栈 局部变量、函数参数...
  • DLUTBruceZhang
  • DLUTBruceZhang
  • 2013年06月20日 15:14
  • 2328

C语言中的各个段

一.前言: C语言程序经过编译连接后形成编译、连接后形成的二进制映像文件由栈,堆,数据段(由三部分部分组成:只读数据段,已经初始化读写数据段,未初始化数据段即BBS)和代码段组成,如下图所示: ...
  • callWuSheng
  • callWuSheng
  • 2013年12月01日 15:55
  • 1005

C语言中变量的地址分配

CPU的内部架构和工作原理                       为什么寄存器比内存快     存储器顺序:寄存器→Cache→内存→外存 1、在C语言中,定义一个变量时,地址是如何分配的?...
  • pengpengjy
  • pengpengjy
  • 2017年02月28日 10:30
  • 812

C语言内存区域分配

阅读Unix环境高级编程的时候,读到了程序存储空间分配,借鉴了网上的一些资料总结如下:   一、C语言可执行代码结构   名称 存储内容 代码段 可执...
  • ycc541
  • ycc541
  • 2015年03月20日 15:33
  • 289

内存区域分配(五个段)

一. 在学习之前我们先看看ELF文件。 ELF分为三种类型:.o 可重定位文件(relocalble file),可执行文件以及共享库(shared library),三种格式基本上从结构...
  • m0_37371085
  • m0_37371085
  • 2017年05月04日 11:35
  • 92

段页式内存管理

1 虚地址的构成 一个进程中所包含的具有独立逻辑功能的程序或数据仍被划分为段,并有各自的段号s,对于段s中的程序或数据,则按照一定的大小将其划分为不同的页。段页式管理时的进程的虚拟地址空间中的虚拟地...
  • xuyuefei1988
  • xuyuefei1988
  • 2013年12月31日 10:28
  • 1557

C语言的内存分配和段错误的处理

在嵌入式的程序设计中对于程序变量的内存的管理尤为重要,因为嵌入式产品的内存资源十分有限,合理分配内存是程序设计人员最优先考虑的问题。当然,一些变量的内存分配不合理有时会导致程序的崩溃(即是段错误)等错...
  • liebao_han
  • liebao_han
  • 2016年10月17日 21:36
  • 351

如何深入学习C语言

学习C语言不是一朝一夕的事情,但也不需要花费十年时间才能精通。如何以最小的代价学习并精通C语言是本文的主题。请注意,即使是“最小的代价”,也绝不是什么捷径,而是以最短的时间取得最多的收获,同时也意味着...
  • wangcong9188
  • wangcong9188
  • 2012年01月03日 22:12
  • 1349

C程序内存区域分配(5个段作用)

参考: http://www.360doc.com/content/11/0330/21/1317564_105977930.shtml http://hi.baidu.com/bitcore/b...
  • crazyhacking
  • crazyhacking
  • 2012年09月16日 16:40
  • 913

C语言的各个段。

C语言程序经过编译连接后形成的二进制映像文件由栈,堆,数据段和代码段组成。其中数据段(由三部分部分组成:只读数据段,已经初始化读写数据段,未初始化数据段即BBS)。 1.栈区(stack):...
  • hamlet_zy
  • hamlet_zy
  • 2017年01月12日 14:24
  • 167
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深入C语言内存区域分配(进程的各个段)详解
举报原因:
原因补充:

(最多只允许输入30个字)