记忆细分

时间:2015-10-03 12:55:12

标签: c++ memory

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

所以我们有4个内存段:Stack,Heap,Data和Code。

首先,我想看看我是否掌握了它的基础

- Stack:一个像堆栈一样被管理的内存段 进入范围后,您在该范围内为该范围分配的内存有限,其中包含有关该范围的信息 (变量等)

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

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

- 数据:包含变量信息的内存段(int x - x代表内存单元格0x0FA20F)

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

如果我没有把它弄好我的问题是:

  • 每个内存段用于什么?

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

  • 使用递归时,从内部调用函数时 函数仍然有代码留在该函数中执行,即 代码保存在人们称之为堆栈的内容中,代码是什么? 常规的Stack段?如果是这样意味着在堆栈内 存储需要在当前范围内执行的常规代码行? 那么用于?

  • 的代码内存段是什么?

如果有人能够组织我脑海中现在的混乱,并且在向我解释每个记忆片段在提到我的问题时完全做了什么的话,我会喜欢它。

3 个答案:

答案 0 :(得分:5)

  

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

您似乎在讨论实模式 x86 arch时的段。现在一切都不一样了。

  

每个内存段用于什么?

现在你应该考虑访问模式。 “代码”是您可以“阅读”和“执行”的内存页面; '数据'='读'和'写'等。

  

关于变量的内存段信息,例如,int x - x代表存储单元0x0FA20F的位置?

无处。命名变量仅存在于源文件(和中间目标代码文件)中。实际代码只有“数字”地址。

  

当使用递归时,当你从函数中调用一个函数并且仍然有代码留在该函数中执行时,该代码会被保存在人们称之为Stack的内容中,该内容是什么?

'Code'是只读的,除了它所在的位置之外,它不能保存在任何地方。保存的是本地(即堆栈)变量和返回地址。两者都保存在堆栈中。

答案 1 :(得分:4)

你关闭了,但并不完全。你指的是一个很老的模型,类似于实模式的x86内存。但是,让我们一起运行,并尝试消除一些困惑......

首先,在讨论内存模型时,C ++(由标准指定)不会对诸如 stack heap 等术语进行任何引用。这些是实施的细节。要继续,请假设您正在谈论典型的x86(32位或64位)PC实现。

C ++本身定义了以下storage durations

  • 静态:程序开始时分配,程序结束时取消分配。具有此存储持续时间的变量大致对应于x86系统上 data 段中的存储。
  • 自动:在封闭代码块的开头分配,并在封闭块的末尾取消分配。这些是本地变量,将在x86系统中的堆栈上分配。
  • 动态:通过new分配,通过delete解除分配。该变量一直存在,直到被删除,并将在您的实现中的上分配。
  • 线程本地:线程开始时分配,线程结束时解除分配。

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

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

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

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

答案 2 :(得分:2)

嗯,大多数情况下,我们实际上有5个段:堆栈,堆,文本(代码),数据,BSS(按段开始块 - 历史名称)。

澄清数据和您错过的数据 - BSS:

  1. 您已初始化的静态和全局变量将转到数据
  2. 没有初始化的静态和全局变量将进入bss并初始化为0
  3. 使用递归时,程序代码存在于Text(代码)中,但函数的局部变量,一些函数参数(取决于体系结构)和返回值(取决于体系结构)都存在于堆栈中。是的,那是在常规堆栈段内。

    在Linux上,您可以在可执行文件上使用size命令为您提供大小的报告:

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

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