Memory management 堆栈和堆是什么,在哪里?

Memory management 堆栈和堆是什么,在哪里?,memory-management,stack,language-agnostic,dynamic-memory-allocation,heap-memory,Memory Management,Stack,Language Agnostic,Dynamic Memory Allocation,Heap Memory,编程语言书籍解释说,值类型是在堆栈上创建的,引用类型是在堆上创建的,但没有解释这两种类型是什么。我还没有读到对此的明确解释。我知道什么是堆栈。但是, 它们在哪里,在什么地方(在真正的计算机内存中) 它们在多大程度上受操作系统或语言运行时控制 它们的范围是什么 是什么决定了它们的大小 什么使人更快 堆栈: 像堆一样存储在计算机RAM中 在堆栈上创建的变量将超出范围并自动解除分配 与堆上的变量相比,分配要快得多 使用实际的堆栈数据结构实现 存储用于参数传递的本地数据、返回地址 当使用太多堆栈时(

编程语言书籍解释说,值类型是在堆栈上创建的,引用类型是在堆上创建的,但没有解释这两种类型是什么。我还没有读到对此的明确解释。我知道什么是堆栈。但是,

  • 它们在哪里,在什么地方(在真正的计算机内存中)
  • 它们在多大程度上受操作系统或语言运行时控制
  • 它们的范围是什么
  • 是什么决定了它们的大小
  • 什么使人更快
      堆栈:

      • 像堆一样存储在计算机RAM中
      • 在堆栈上创建的变量将超出范围并自动解除分配
      • 与堆上的变量相比,分配要快得多
      • 使用实际的堆栈数据结构实现
      • 存储用于参数传递的本地数据、返回地址
      • 当使用太多堆栈时(主要来自无限或太深的递归、非常大的分配),可能会出现堆栈溢出
      • 在堆栈上创建的数据可以在没有指针的情况下使用
      • 如果您确切地知道在编译之前需要分配多少数据,并且数据量不是太大,那么可以使用堆栈
      • 通常在程序启动时已经确定了最大大小
      堆:

      • 像堆栈一样存储在计算机RAM中
      • 在C++中,堆上的变量必须手动销毁,并且永远不会超出范围。通过
        delete
        delete[]
        free
        释放数据
      • 与堆栈上的变量相比,分配速度较慢
      • 按需分配数据块供程序使用
      • 当存在大量分配和解除分配时,可能会出现碎片
      • 在C++或C中,堆上创建的数据将由指针指向并分配给<代码>新< /COD>或 MalOC<<代码> >
      • 如果请求分配的缓冲区太大,则可能会导致分配失败
      • 如果您不确切知道在运行时需要多少数据,或者需要分配大量数据,则可以使用堆
      • 负责内存泄漏
      示例:

      intfoo()
      {
      char*pBuffer;//堆栈
      当你调用一个函数时,该函数的参数加上一些其他开销被放在堆栈上。一些信息(比如返回时去哪里)也存储在堆栈中。
      在函数中声明变量时,该变量也会在堆栈上分配

      取消分配堆栈非常简单,因为您总是按照与分配相反的顺序取消分配。在您输入函数时添加堆栈内容,在您退出函数时删除相应的数据。这意味着您往往停留在堆栈的一个小区域内,除非您调用了大量调用其他函数的函数(或创建递归解决方案)

      heap是一个通用名称,用于存放动态创建的数据。如果您不知道您的程序将要创建多少艘宇宙飞船,则可能会使用新的(或malloc或同等名称)操作员创建每一艘宇宙飞船。这个分配将持续一段时间,所以我们很可能会以不同于我们创建它们的顺序释放东西


      因此,堆要复杂得多,因为最终会有未使用的内存区域与未使用的内存块交织在一起—内存会被碎片化。找到所需大小的可用内存是一个困难的问题。这就是为什么应该避免堆(尽管仍然经常使用堆)

      实施 堆栈和堆的实现通常取决于运行时/操作系统。游戏和其他性能关键的应用程序通常会创建自己的内存解决方案,从堆中获取大量内存,然后在内部分发,以避免依赖操作系统获取内存

      只有当你的内存使用量与正常情况大不相同时,这才是可行的——例如,在游戏中,你在一个巨大的操作中加载一个关卡,然后在另一个巨大的操作中扔掉所有关卡

      内存中的物理位置
      这一点没有你想象的那么重要,因为一种称为的技术使你的程序认为你可以访问物理数据在其他地方(甚至在硬盘上!)的某个地址。你得到的堆栈地址随着调用树的加深而增加。堆的地址是不可预测的(即特定于实现)而且坦率地说并不重要。

      堆栈是内存的一部分,可以通过几个关键的汇编语言指令进行操作,如“pop”(从堆栈中删除并返回值)和“push”(将值推送到堆栈),但也调用(调用子例程-这会将地址推送到堆栈)和return(从子例程返回-从堆栈中弹出地址并跳转到它)。它是堆栈指针寄存器下面的内存区域,可以根据需要进行设置。堆栈还用于向子例程传递参数,以及在调用子例程之前保留寄存器中的值

      堆是操作系统提供给应用程序的内存的一部分,通常通过malloc之类的系统调用。在现代操作系统上,此内存是一组只有调用进程才能访问的页面

      堆栈的大小在运行时确定,通常不会在程序启动后增长。在C程序中,堆栈需要足够大,以容纳每个函数中声明的每个变量。堆将根据需要动态增长,但操作系统最终会进行调用(堆的增长通常会超过val)