程序在内存中的布局

前言

🐶“有个小朋友问我,程序在系统中的布局是什么样的?今天我们来看看…”

准备这一篇介绍,是为了介绍缓冲区溢出攻击。

正文内容,翻译Memory Layout of C Programs

我不清楚,现在程序被加载进入内存的布局是不是这样了。

我也没有查看网上是不是有详细内容的文章。先翻译着。

我目前只用到栈(栈帧),暂时以这篇文章介绍的内容为准。栈帧的内容,我在下一篇文章中用gdb调试的方式展示。

这篇文章的另一背景是虚拟内存,它可以帮助我们更好的理解。

注:堆栈指栈,堆指堆。


c 程序的内存布局

C程序的典型内存表示由以下部分组成:

  1. Text segment
  2. Initialized data segment
  3. Uninitialized data segment
  4. Stack
  5. Heap

在这里插入图片描述

A typical memory layout of a running process

1. Text Segment

Text Segment,也称为代码段或简称为文本,是目标文件或内存中程序的一部分,其中包含可执行指令。

作为内存区域,文本段放置在堆或栈下方,以防止堆和栈溢出覆盖它。

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


2. Initialized Data Segment

Initialized Data Segment,通常简称为数据段。数据段是程序虚拟地址空间的一部分,它包含程序员初始化的全局变量和静态变量。

注意,数据段不是只读的,因为变量的值可以在运行时更改。

这个段可以进一步划分为初始化的只读区域和初始化的读写区域。

例如,在C中由char s [] =“ hello world”定义的全局字符串以及在main(即global)外部的int debug = 1之类的C语句将存储在初始化的读写区域中。 像const char * string =“ hello world”这样的全局C语句使字符串文字“ hello world”存储在初始化的只读区域中,而字符指针变量string串存储在初始化的读写区域中。

例如:static int i = 10将存储在数据段中,而全局int i = 10也将存储在数据段中


3. Uninitialized Data Segment

Uninitialized Data Segment,通常称为“ bss”段,以古老的汇编程序运算符命名,其代表“block started by symbol.” (译者:我不知道这个古老的汇编运算符是个啥)。 在程序开始执行之前,内核将该段中的数据初始化为算术0。

程序中未初始化全局变量和静态变量,从数据段的末尾开始,这些变量被初始化为零。

例如,一个变量声明static int i; ,它将包含在BSS段中。

例如,一个声明为int j的全局变量,将包含在BSS段中。


4. Stack

传统上,栈区域与堆区域邻接,并且朝相反的方向生长; 当栈指针遇到堆指针时,可用内存就用完了。 (借助现代的大型地址空间和虚拟内存技术,它们可以放置在几乎任何地方,但它们通常仍会朝相反的方向生长。

栈区域包含程序栈(一种LIFO结构),通常位于内存的较高部分。 在标准PC x86计算机体系结构上,它向地址0增长; 在其他一些架构上,它却朝着相反的方向发展。 一个“栈指针”寄存器跟踪栈的顶部。 每次将值“推入”堆栈时都会对其进行调整。 为一个函数调用压入的一组值称为“堆栈帧”(stack frame); 堆栈帧至少包含一个返回地址。(可以包含多个返回地址呢?)

栈,用于存储局部变量以及每次调用函数时保存的信息。 每次调用函数时,返回位置的地址和有关调用者环境的某些信息(例如某些机器寄存器)都保存在堆栈中。 然后,新调用的函数在堆栈上为其自动和临时变量分配空间。 这是C中的递归函数的工作方式。 每次递归函数调用自身时,都会使用一个新的stack frame,因此一组变量不会干扰该函数另一个实例的变量。


5. Heap

(Heap)堆是动态内存分配通常发生的地方。

堆区域从BSS段的末尾开始,并从那里扩展到更大的地址。堆区域由mallocreallocfree管理,它们可以使用brksbrk系统调用来调整其大小。 堆区域由进程中的所有共享库和动态加载的模块共享。(关于共享库映射空间,我不清楚)


examples

译者:size命令的使用:Linux size命令和C程序的存储空间布局

  1. 尝试下简单的C程序

    #include <stdio.h> 
    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          8       1216        4c0    memory-layout
    
  2. 添加一个全局变量,检查bss的大小

    #include <stdio.h> 
    /*译者:如果增加一个没有变化,增加两个试试*/
    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中

    #include <stdio.h> 
    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)中

    #include <stdio.h> 
    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)中

    #include <stdio.h> 
    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
    


本文由Narendra Kangralkar编写。如果你发现任何不正确的地方,请写评论,或者你想分享更多关于上面讨论的话题的信息。



Source:
http://en.wikipedia.org/wiki/Data_segment
http://en.wikipedia.org/wiki/Code_segment
http://en.wikipedia.org/wiki/.bss
http://www.amazon.com/Advanced-Programming-UNIX-Environment-2nd/dp/0201433079



Recommended Posts:

Article Tags : CC-Dynamic Memory Allocationsystem-programming

Practice Tags : C

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值