Memory Segments

Memory Segments

本文关键字:Segments Memory      更新时间:2023-10-16

我目前正在学习c++中的动态内存,在试图完全理解和理解程序内存中的内存段时,我发现了许多麻烦。

所以我们有4个内存段:堆栈,堆,数据和代码。

首先我想看看我是否掌握了它的基本知识

- Stack:像堆栈一样被管理的内存段一旦进入一个作用域,就会在该段中为该作用域分配有限的内存,其中应该包含有关该作用域的信息(变量等)

- Heap:一个动态内存段,它是无限的,当你在该段中分配内存时,它不会被删除,因为你退出了所使用的代码或函数的作用域,它需要被你或gc删除(如果它不再不可达)

- Code:包含CPU需要执行的代码的内存段

- Data:一个包含变量信息的内存段(int x - x表示内存单元0x0FA20F)

我的第一个问题是,我做对了吗?我真的不确定....

如果我没有答对,我的问题是:

  • 每个内存段用于什么?

  • 其中关于变量的内存段信息,例如,int x - x表示0x0FA20F所在的存储单元?

  • 使用递归时,当从函数中还有代码要执行代码保存在人们所说的堆栈中,这指的是什么?,常规的堆栈段?如果是,是否意味着在堆栈内需要在当前作用域中执行的常规代码行是否被存储?那么代码内存段是用来做什么的呢?

如果有人能整理一下我现在脑子里的混乱,并在参考我的问题时向我解释一下每个记忆段的全部作用,我将会很高兴。

你已经很接近了,但还差得很远。你指的是一个相当老的模型,类似于真实模式的x86内存。然而,让我们运行它,并试图澄清一些困惑…

首先,c++(由标准指定)在谈论内存模型时没有引用任何术语,如stackheap。这些是实现的细节。接下来,让我们假设您谈论的是典型的x86(32位或64位)PC实现。

c++本身定义了以下存储持续时间:

  • static:在程序开始时分配,在程序结束时释放。具有此存储持续时间的变量大致对应于x86系统上data段中的存储。
  • automatic:在封装代码块的开始处分配,在封装代码块的结束处释放。这些是本地变量,在x86系统中将在堆栈上分配。
  • dynamic:通过new分配,通过delete释放。该变量一直存在,直到被删除,并且在您的实现中将被分配到上。
  • thread local:线程开始时分配,线程结束时释放。

还有一个bss段,用于零初始化变量。

每个函数调用都有自己的堆栈帧,其中包括所有具有自动存储持续时间的变量,以及函数的参数、返回值的空间和调用函数状态的存储副本。当函数返回时,将恢复此状态,以便您可以继续离开的地方。该状态的一部分是指令指针,它是指向下一个要执行的指令的指针。指令序列本身总是在代码段中;它不会被复制到堆栈中。

这是一种简化,对于大多数用途,您不需要知道存储持续时间的标准定义之外的任何内容;其余部分是实现细节!

[注:现代用法倾向于考虑内存访问权限。代码将被加载到只读可执行的内存页面中,而数据(包括堆栈)将被加载到读写页面中,这些页面理想地标记为不可执行。除了stack/heap之外,任何进一步的区分都是没有意义的。

我的第一个问题是,我做对了吗?我真的不确定....

你似乎在谈论real-mode x86 arch时代的段。现在一切都不同了。

每个内存段是用来做什么的?

现在你应该考虑访问模式。"代码"是你可以"读取"answers"执行"的内存页;'Data' = 'read'和'write'等

关于变量的内存段信息,例如int x - x表示内存单元0x0FA20F,位于哪个内存段?

。命名变量只存在于源文件(和中间目标代码文件)中。实际代码只有'number'地址。

当使用递归时,当你在函数内部调用函数时,仍然有代码要在该函数中执行,这些代码被保存在人们所说的堆栈中,它指的是什么?

'Code'是只读的,它不会被保存在任何地方,除非它所在的地方。保存的是本地(即堆栈)变量和返回地址。两者都保存在堆栈上。

嗯,基本上正确,我们实际上有5个段:堆栈,堆,文本(代码),数据,BSS(块从段开始-历史名称)。

澄清数据和你遗漏的数据- BSS:

  1. 初始化的静态和全局变量将转到data
  2. 未初始化的静态变量和全局变量将进入bss并初始化为0

当使用递归时,程序代码驻留在Text(代码)中,但是函数的局部变量、一些函数参数(取决于体系结构)和返回值(取决于体系结构)驻留在堆栈中。是的,这是在正常的堆栈段内。

在Linux上,你可以在一个可执行文件上使用size命令来给你一个大小的报告:

[root@boran ~]# size /bin/bash
text       data     bss     dec     hex filename
902580    35984   22920  961484   eabcc /bin/bash

当我想启动我的bash解释器时,操作系统将分配文本部分并将代码复制到它。它将分配数据段并将数据复制到其中,但它将分配BSS的大小并将其归零。之后,每个程序都有一个堆栈大小,操作系统会动态地把它分成块给你,让你跟上。堆是通过调用系统调用手动分配的东西。堆和堆栈大小都可以限制。最后,程序将通过跳转到代码节中的地址来调用。