📜  C程序的内存布局

📅  最后修改于: 2021-05-26 02:34:18             🧑  作者: Mango

C程序的典型内存表示包括以下部分。
1.文字区隔
2.初始化的数据段
3.未初始化的数据段
4.堆叠
5.堆

正在运行的进程的典型内存布局
1.文字区隔:
文本段,也称为代码段或简称为文本,是目标文件或内存中程序的一部分,其中包含可执行指令。
作为内存区域,可以在堆或堆栈下方放置一个文本段,以防止堆和堆栈溢出覆盖它。

通常,文本段是可共享的,因此对于频繁执行的程序(例如文本编辑器,C编译器,shell等),只需要在内存中保存一个副本即可。此外,文本段通常是只读的,以防止程序意外修改其指令。

2.初始化的数据段:
初始化的数据段,通常简称为数据段。数据段是程序的虚拟地址空间的一部分,其中包含由程序员初始化的全局变量和静态变量。
请注意,数据段不是只读的,因为可以在运行时更改变量的值。
该段可以进一步分为初始化的只读区域和初始化的读写区域。
例如,在C中由char s [] =“ hello world”定义的全局字符串以及在主(即全局)外部的int debug = 1之类的C语句将存储在初始化的读写区域中。像const char * 字符串 =“ hello world”这样的全局C语句使字符串字面量“ hello world”存储在初始化的只读区域中,而字符指针变量字符串在初始化的读写区域中。
例如:static int i = 10将存储在数据段中,而global int i = 10也将存储在数据段中

3.未初始化的数据段:
未初始化的数据段通常称为“ bss ”段,以古老的汇编程序运算符命名,其代表“以符号开头的块”。在程序开始执行之前,内核将该段中的数据初始化为算术0。
未初始化的数据从数据段的末尾开始,包含所有初始化为零或在源代码中没有显式初始化的全局变量和静态变量。
例如,一个变量声明为static int i;将包含在BSS细分中。
例如,一个声明为int j的全局变量;将包含在BSS细分中。

4.堆栈:
传统上,堆栈区域与堆区域相邻,并且朝相反的方向增长;当堆栈指针遇到堆指针时,可用内存就用完了。 (利用现代的大型地址空间和虚拟内存技术,它们可以放置在几乎任何地方,但它们通常仍沿相反的方向生长。)
堆栈区域包含程序堆栈,即LIFO结构,通常位于内存的较高部分。在标准的PC x86计算机体系结构上,它向地址0增长;在其他一些架构上,它朝相反的方向发展。 “堆栈指针”寄存器跟踪堆栈的顶部。每次将值“推入”堆栈时都会对其进行调整。为一个函数调用压入的一组值称为“堆栈帧”;即“堆栈帧”。堆栈帧至少包含一个返回地址。
堆栈,用于存储自动变量,以及每次调用函数保存的信息。每次调用一个函数时,要返回的地址和有关调用者环境的某些信息(例如某些机器寄存器)都保存在堆栈中。然后,新调用的函数在堆栈上为其自动和临时变量分配空间。这就是C中的递归函数如何工作的方式。每次递归函数调用其自身时,都会使用一个新的堆栈框架,因此一组变量不会干扰该函数另一个实例的变量。

5.堆:
堆是通常进行动态内存分配的段。
堆区域开始于BSS段的末尾,并从那里开始扩展到更大的地址。堆区域由malloc,realloc和free管理,它们可以使用brk和sbrk系统调用来调整其大小(请注意,不需要使用brk / sbrk和单个“堆区域”来履行malloc / realloc / free;也可以使用mmap来实现它们,以将虚拟内存的潜在不连续区域保留到进程的虚拟地址空间中)。堆区域由进程中的所有共享库和动态加载的模块共享。

例子。
size(1)命令报告文本,数据和bss段的大小(以字节为单位)。 (有关更多详细信息,请参考size(1)的手册页)

1.检查以下简单的C程序

C
#include 
 
int main(void)
{
    return 0;
}


C
#include 
 
int global; /* Uninitialized variable stored in bss*/
 
int main(void)
{
    return 0;
}


C
#include 
 
int global; /* Uninitialized variable stored in bss*/
 
int main(void)
{
    static int i; /* Uninitialized static variable stored in bss */
    return 0;
}


C
#include 
 
int global; /* Uninitialized variable stored in bss*/
 
int main(void)
{
    static int i = 100; /* Initialized static variable stored in DS*/
    return 0;
}


C
#include 
 
int global = 10; /* initialized global variable stored in DS*/
 
int main(void)
{
    static int i = 100; /* Initialized static variable stored in DS*/
    return 0;
}


[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
960        248          8       1216        4c0    memory-layout

2.让我们在程序中添加一个全局变量,现在检查bss的大小(以红色突出显示)。

C

#include 
 
int global; /* Uninitialized variable stored in bss*/
 
int main(void)
{
    return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
 960        248         12       1220        4c4    memory-layout

3.让我们添加一个静态变量,该变量也存储在bss中。

C

#include 
 
int global; /* Uninitialized variable stored in bss*/
 
int main(void)
{
    static int i; /* Uninitialized static variable stored in bss */
    return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
 960        248         16       1224        4c8    memory-layout

4.让我们初始化静态变量,然后将其存储在数据段(DS)中

C

#include 
 
int global; /* Uninitialized variable stored in bss*/
 
int main(void)
{
    static int i = 100; /* Initialized static variable stored in DS*/
    return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
960         252         12       1224        4c8    memory-layout

5.让我们初始化全局变量,然后将其存储在数据段(DS)中

C

#include 
 
int global = 10; /* initialized global variable stored in DS*/
 
int main(void)
{
    static int i = 100; /* Initialized static variable stored in DS*/
    return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
960         256          8       1224        4c8    memory-layout

来源:

http://en.wikipedia.org/wiki/Data_segment

http://en.wikipedia.org/wiki/Code_segment

http://en.wikipedia.org/wiki/.bss

想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。