• 什么是堆叠和堆叠?
  • 他们在电脑记忆中身处何方?
  • 它们在多大程度上受到操作系统或语言运行时间的控制?
  • 其范围是什么?
  • 是什么决定了它们的大小?
  • 是什么让一个更快?

当前回答

简单的说, 堆栈是创建本地变量的地方。 另外, 每次你调用一个子常规, 程序计数器( 指针到下一个机器指令) 和任何重要的登记器, 有时参数会被推到堆叠上。 然后, 子常规内的任何本地变量都会被推到堆叠上( 并在那里使用 ) 。 当子常规完成后, 所有的东西都会从堆叠上跳出来。 PC 和注册数据都会得到并放回原位, 这样您的程序就可以继续其快乐的方式 。

堆积是用( 明确的“ 新 ” 或“ 分配 ” 调用 ” 调用 ) 来分配记忆的动态空间。 它是一个特殊的数据结构, 可以跟踪大小不一的记忆区块及其分配状况 。

在“古典”系统中,内存记录仪被设置得非常清晰,使堆叠指针从记忆的底部开始,堆积指针从顶部开始,它们相互向上发展。如果它们重叠,你就退出内存。虽然这与现代多轨操作系统不起作用。每条线必须有自己的堆叠,并且它们可以动态地生成。

其他回答

其他人对大中风的反应也很好, 所以我要讲一些细节。

  1. 堆放和堆放不需要是单数的 。 堆放和堆放的多处常见情况是, 您在一个过程中拥有多个线条。 在此情况下, 每个线条都有自己的堆放。 您也可以有多个堆放。 例如, 某些 DLL 配置可能导致不同堆放的 DLL 分配不同的 DLL , 这就是为什么释放不同图书馆分配的内存通常是一个坏主意 。

  2. 在 C 中,您可以通过使用单花,它分配在堆叠上,而不是 Alloc,它分配在堆肥上。这个记忆不会保存在您的返回语句中,但它对刮痕缓冲很有用。

  3. 在 Windows 上做一个不使用很多内容的大型临时缓冲区不是免费的。 这是因为编译器将生成一个堆叠探测器循环, 每次输入您的函数时都会被调用, 以确保堆叠存在( 因为 Windows在堆叠的末尾使用一个单个的守护页面来检测堆叠的生长需要。 如果您访问堆叠尾端的多页内存, 您将会崩溃 ) 。 例如 :

void myfunction()
{
   char big[10000000];
   // Do something that only uses for first 1K of big 99% of the time.
}

因为有些答案没有被选中,所以我会贡献我的力量。

令人惊讶的是,没有人提到,不仅在外来语言(邮政(邮政)或平台(英特机Itium)中,而且在互联网上,都能找到多个(即与运行的OS级别线索数量无关)调呼堆叠(即与运行的OS级别线索数量无关)纤维纤维, 绿线以及一些执行《公约》和《公约》共管.

纤维、绿线和合金在许多方面都相似,导致许多混乱。 纤维和绿线之间的区别在于前者使用合作性多任务,而后者可能具有合作性或先发制人(甚至两者兼而有之)的特点。 关于纤维和合金之间的区别,请参看在这里.

无论如何,两种纤维、绿线和共程的目的都具有同时执行的多重功能,但是,平行平行(见这个问题在一个OS级线内,以有组织的方式将控制权相互交替转移。

当使用纤维、绿线或合金时,你通常通常每个函数都有单独的堆叠 。 (在技术上, 不只是堆叠, 而整个执行环境是每个函数。 最重要的是, CPU 注册 。) 对于每串线索, 都有与同时运行的函数一样多的堆叠, 并且线索正在根据程序逻辑执行每个函数之间切换。 当一个函数运行到尾端时, 它的堆叠会被销毁 。 因此,堆叠的数量和寿命是动态的,并且不取决于操作系统级别线索的数量 !

请注意,我说过: "通常通常每个函数有一个单独的堆叠。堆叠无文最引人注意的堆叠式C++的C++实施软 软 软 软 软 体微软 PPPL数(_S)async/await。 (然而, C++'s可恢复功能(a.k.a. " )asyncawait" (C++17提案,可能使用无堆叠的共程。 )

C++标准图书馆的Fibers提案即将提出。还有第三方。图书馆图书馆绿色线在Python和Ruby等语言中极为流行。

堆叠 :

  • 存储在计算机内存中 就像堆积物一样
  • 堆叠上创建的变量将超出范围, 自动进行交易 。
  • 与堆积上的变量相比,分配速度要快得多。
  • 采用实际的堆叠数据结构。
  • 存储本地数据, 返回地址, 用于通过参数 。
  • 当堆叠使用过多时(大部分来自无限重现或过深重重循环,分配量很大), 堆叠就会溢出。
  • 在堆栈上创建的数据可以不用指针使用 。
  • 如果您确切知道在编译时间之前需要分配多少数据, 并且数据并不太大, 您就会使用堆叠 。
  • 通常在程序启动时已经确定了最大尺寸 。

热量 :

  • 存储在计算机内存 和堆叠一样。
  • 在 C+++ 中, 堆积上的变量必须手动销毁, 并且绝对不能脱离范围。 数据以delete, delete[],或free.
  • 相对于堆叠上的变量, 较慢分配速度 。
  • 用于按需分配一组数据供程序使用。
  • 当有大量拨款和交易时,就有可能支离破碎。
  • 在C++ 或C++ 或C中,在堆积上生成的数据将用指针指出,并用newmalloc两者分别。
  • 如果要求分配的缓冲量太大,则可以造成分配失败。
  • 如果您不知道运行时需要多少数据, 或者需要分配大量数据, 您就会使用这种数据 。
  • 负责内存泄漏

示例:

int foo()
{
  char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
  bool b = true; // Allocated on the stack.
  if(b)
  {
    //Create 500 bytes on the stack
    char buffer[500];

    //Create 500 bytes on the heap
    pBuffer = new char[500];

   }//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;

我有些话要说,尽管主要要点已经涵盖在内。

堆堆叠

  • 非常快速的进入。
  • 存储在记录和档案管理中。
  • 函数调用与本地变量和已通过的函数参数一起装入这里 。
  • 当程序超出范围时,空间会自动释放。
  • 存储在相继内存中 。

堆肥

  • 与Stack相比,Stack的准入速度缓慢。
  • 存储在记录和档案管理中。
  • 动态创建的变量存储在这里, 以后需要使用后释放分配的内存 。
  • 存储到记忆分配的地方 指示器总是能存取

有趣的是:

  • 如果功能电话储存在堆积中,就会造成两点混乱:
    1. 由于在堆叠中相继存储, 执行速度会更快。 堆积中的堆积会导致大量时间消耗, 从而使整个程序的执行速度放慢 。
    2. 如果将功能储存在堆积中(指针指向的沉降器),就不可能返回调用地址(堆叠是由于内存的顺序存储而提供的) 。

其他人直接回答了你的问题,但是,在试图理解堆叠和堆叠时,我认为,考虑传统的UNIX进程的记忆布局(没有线条和线条)是有益的。mmap()- 以基于分配器为基础。记忆管理词汇表网页上有一个内存布局图。

堆堆和堆堆堆传统上位于进程的虚拟地址空间的对面。当访问时,堆堆会自动增长,最多以内核设定的大小(可以与setrlimit(RLIMIT_STACK, ...)))当内存分配器援引brk()sbrk()系统呼叫,绘制更多页的物理内存 进入该过程的虚拟地址空间。

在没有虚拟内存的系统中,例如一些嵌入系统,通常适用同样的基本布局,但堆叠和堆积大小固定。然而,在其他嵌入系统(例如基于微芯片的微控制器)中,程序堆叠是一个单独的内存块,无法通过数据移动指示处理,只能通过程序流指示(调用、返回等)进行间接修改或阅读。多个堆叠。从这个意义上说,堆叠是CPU结构的一个元素。