C语言 段详细讲解

C语言 段详细讲解在 C 语言中 段 Segment 通常是指内存中的一段连续区域 用于存储程序中的数据或代码

大家好,欢迎来到IT知识分享网。

在C语言中,”段”(Segment)通常是指内存中的一段连续区域,用于存储程序中的数据或代码。C语言中的段可以分为以下几个部分:

这些段的概念在早期的C语言实现中非常重要,因为它们直接映射到计算机的物理内存结构。然而,在现代操作系统中,这些概念仍然存在,但它们更多的是一种抽象,实际的内存管理由操作系统负责。

 

f03796b69a684dbb968e9aa6d05323c4.jpeg

代码段是执行指令集合  .data是初始化数据    .bss未初始化数

  在DOS编程中,程序员可能会使用`__segment`或`__ds`等关键字来指定变量或函数应该放在哪个段中。这些关键字是特定于编译器和操作系统的,并不是C语言标准的一部分。

通常一个程序分为

a8f745e27b24c8ab1421ef223550afd0.png

再谈应用程序分段: 数据段、代码段、BSS段以及堆和栈

分段本身就是一个比较复杂的内容,值得再专门写一遍文章介绍,本文再前文基础上再谈应用程序的分段


ELF 文件

逆向分析:ELF 文件组成50 赞同 · 2 评论文章

讲过 ELF 文件结构大致如下图:

format,png

我们知道 ELF 文件包含三种类型:可重定位文件(*.o)、可执行文件、以及共享库(share library)。

三种文件格式从结构上来说基本一致,只是具体到每一个结构不同。

代码段(.text)是可执行指令的集合;数据段(.data)和 BSS 段(.bss)是数据的集合,其中.data 表示已经初始化的数据,.bss 表示未初始化的数据。

从可执行程序的角度来说,如果一个数据未被初始化,就不需要为其分配空间,所以.data 和.bss 的区别就是 .bss 并不占用可执行文件的大小,仅仅记录需要用多少空间来存储这些未初始化的数据,而不分配实际空间。

2 应用程序的组成

2.1 组成

从汇编语言角度,一个程序分为:

  • 数据段
  • 堆栈段
  • 代码段
  • 扩展段

站在高级语言,如 C 语言,一个程序分为如下段(当然还有其他段,这里列举主要的段):

  • 代码段
  • 数据段
  • BSS 段

我们可以看到一个可执行程序至少包含:代码段 + 数据段 + BSS 段

一般情况下,一个可执行二进制程序(在 linux 下为一个进程单元),在存储时(没有加载到内存运行),至少拥有三个部分,分别是代码段(text)、数据段(data)、和BSS 段。

这三个部分一起组成了可执行程序(可能还有其他的段,和平台相关)

当应用程序运行时(运行态),此时需要另外两个域:堆和栈。正在运行的程序:代码段 + 数据段 + BSS 段 + 堆 + 栈

如图所示为可执行应用程序存储态运行态的结构对照图。一个正在运行的 C 程序占用的内存区域分为代码段、数据段(初始化数据)、BSS 段(未初始化数据)、堆和栈 5 部分

format,png

2.2 内存管理

在将应用程序加载到内存空间执行时,操作系统负责代码段、数据段和 BSS 段的加载,并在内存中为这些段分配空间。栈也由操作系统管理,不需要程序员显示的管理;堆段需要程序员自己管理,显示的申请和释放。

动态分配

在运行时执行动态分配。需要程序员显示管理,通过 malloc 申请,并且需要手动 free 掉,否则会造成内存泄漏。

静态分配

在编译时就已经决定好了分配多少 Text+Data+Bss+Stack(静态分配)。

静态分配的内存在进程结束后由系统释放(Text+Data),Stack 上的数据则在退出函数后立即被销毁。

3 各段说明

3.1 代码段

代码段在内存中被映射为只读。它是由编译器在编译链接时自动计算的。通常是用来存放程序执行的指令。代码段输入静态内存分配。

3.2 数据段

通常用来存放程序中已初始化的(非 0)全局变量和静态局部变量。数据段的起始位置由链接定位文件确认,大小在编译链接时自动分配。数据段属于静态内存分配

3.3 BSS 段

bss 是英文 Block by Symbol 的简称。通常用来存放程序中未初始化和初始化为 0的全局变量的一块内存区域,在程序载入时由内核清零。数据段属于静态内存分配

3.4 堆

堆保存函数内部动态分配(malloc 或 new)的内存,是另外一种用来保存程序信息的数据结构。

堆是先进先出(FIFO)数据结构。堆的地址空间是向上增加,即当堆上保存的数据越多,堆的地址越高。动态内存分配

注意:堆内存需要程序员手动管理内存,通常适用于较大的内存分配,如频繁的分配较小的内存,容易导致内存碎片化。

3.5 栈

栈保存函数的局部变量(不包括 static 修饰的变量),参数以及返回值。是一种后进先出(LIFO)的数据结构。

在调用函数或过程后,系统会清除栈上保存的局部变量、函数调用信息及其他信息。

栈的另外一个重要特征是,它的地址空间 向下减少,即当栈上保存的数据越多,栈的地址越低。静态内存分配

注意,由于栈的空间通常比较小,一般 linux 程序只有几 M,故局部变量,函数入参应该避免出现超大栈内存使用,比如超大结构体,数组等,避免出现 stack overflow

cd914924947048bc84d0b94df51f1152.jpegELF文件类型

逆向分析:ELF 文件组成 – 知乎

程序经过编译、连接后形成的二进制文件由栈、堆、数据段(由三部分组成:只读数据段、已经初始化读写数据段、未初始化数据段)和代码段组成。

1.栈区:由编译器自动分配释放,存放函数的参数值,局部变量等值。其操作方式类似于数据结构中的栈。

2.堆区:一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。

3.代码段:存放函数体的二进制代码。

(1)栈(satck):由系统自动分配。例如,声明在函数中一个局部变量int b;系统自动在栈中为b开辟空间。

(2)堆(heap):需程序员自己申请(调用malloc,realloc,calloc),并指明大小,并由程序员进行释放。容易产生memory leak.

eg:

2.申请大小的限制

(1)栈:在windows下栈是向底地址扩展的数据结构,是一块连续的内存区域(它的生长方向与内存的生长方向相反)。栈的大小是固定的。如果申请的空间超过栈的剩余空间时,将提示overflow。

(2)堆:堆是高地址扩展的数据结构(它的生长方向与内存的生长方向相同),是不连续的内存区域。这是由于系统使用链表来存储空闲内存地址的,自然是不连续的,而链表的遍历方向是由底地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。

3.系统响应:

(1)栈:只要栈的空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

(2)堆:首先应该知道操作系统有一个记录空闲内存地址的链表,但系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的free语句才能正确的释放本内存空间。另外,找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

说明:对于堆来讲,对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,

4.申请效率

(1)栈由系统自动分配,速度快。但程序员是无法控制的

(2)堆是由malloc分配的内存,一般速度比较慢,而且容易产生碎片,不过用起来最方便。

5.堆和栈中的存储内容

(1)栈:在函数调用时,第一个进栈的主函数中后的下一条语句的地址,然后是函数的各个参数,参数是从右往左入栈的,然后是函数中的局部变量。注:静态变量是不入栈的。

当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续执行。

(2)堆:一般是在堆的头部用一个字节存放堆的大小。

6.存取效率

(1)堆:char *s1=”hellow tigerjibo”;是在编译是就确定的

(2)栈:char s1[]=”hellow tigerjibo”;是在运行时赋值的;用数组比用指针速度更快一些,指针在底层汇编中需要用edx寄存器中转一下,而数组在栈上读取。

补充:

栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

7.分配方式:

(1)堆都是动态分配的,没有静态分配的堆。

(2)栈有两种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的。它的动态分配是由编译器进行释放,无需手工实现。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/121306.html

(0)
上一篇 2025-10-24 14:20
下一篇 2025-10-24 14:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信