堆栈和堆的内容和位置是什么?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆栈和堆的内容和位置是什么?相关的知识,希望对你有一定的参考价值。

编程语言书籍解释了在堆栈上创建了值类型,并且在堆上创建了引用类型,而没有解释这两者是什么。我还没有看清楚这个问题。我理解堆栈是什么。但,

  • 它们在哪里以及它们是什么(物理上在真实计算机的记忆中)?
  • 它们在多大程度上受OS或语言运行时控制?
  • 它们的范围是什么?
  • 是什么决定了它们的大小?
  • 是什么让一个更快?
答案

堆栈是作为执行线程的临时空间留出的内存。调用函数时,会在堆栈顶部为区域变量和一些簿记数据保留一个块。当该函数返回时,该块将变为未使用状态,并可在下次调用函数时使用。堆栈始终以LIFO(后进先出)顺序保留;最近保留的块始终是要释放的下一个块。这使得跟踪堆栈非常简单;从堆栈中释放块只不过是调整一个指针。

堆是为动态分配留出的内存。与堆栈不同,堆中的块的分配和释放没有强制模式;您可以随时分配一个块并随时释放它。这使得在任何给定时间跟踪堆的哪些部分被分配或释放变得更加复杂;有许多自定义堆分配器可用于调整不同使用模式的堆性能。

每个线程都获得一个堆栈,而应用程序通常只有一个堆(尽管为不同类型的分配设置多个堆并不罕见)。

直接回答您的问题:

它们在多大程度上受操作系统或语言运行时控制?

操作系统在创建线程时为每个系统级线程分配堆栈。通常,语言运行库调用OS来为应用程序分配堆。

它们的范围是什么?

堆栈附加到线程,因此当线程退出堆栈时回收。堆通常在应用程序启动时由运行时分配,并在应用程序(技术过程)退出时回收。

是什么决定了它们的大小?

创建线程时设置堆栈的大小。堆的大小在应用程序启动时设置,但可以在需要空间时增长(分配器从操作系统请求更多内存)。

是什么让一个更快?

堆栈更快,因为访问模式使得从中分配和释放内存变得微不足道(指针/整数简单地递增或递减),而堆在分配或释放中涉及更复杂的簿记。此外,堆栈中的每个字节都经常被频繁地重用,这意味着它往往被映射到处理器的缓存,使其非常快。堆的另一个性能影响是堆(主要是全局资源)通常必须是多线程安全的,即每个分配和释放需要 - 通常 - 与程序中的“所有”其他堆访问同步。

明确的示范: 图像来源:vikashazrati.wordpress.com

另一答案

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

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

堆栈的大小在运行时确定,并且通常在程序启动后不会增长。在C程序中,堆栈需要足够大以容纳每个函数中声明的每个变量。堆将根据需要动态增长,但操作系统最终会进行调用(它通常会使堆的增长超过malloc请求的值,因此至少某些未来的malloc将不需要返回到内核获得更多内存。此行为通常是可自定义的)

因为你在启动程序之前已经分配了堆栈,所以在使用堆栈之前你永远不需要malloc,所以这是一个小优势。在实践中,很难预测具有虚拟内存子系统的现代操作系统的速度和速度会有多快,因为页面的实现方式和存储位置是实现细节。

另一答案

我想很多其他人在这件事上给了你大致正确的答案。

然而,遗漏的一个细节是“堆”实际上可能被称为“免费商店”。这种区别的原因是原始的免费存储是使用称为“二项式堆”的数据结构实现的。出于这个原因,从malloc()/ free()的早期实现中分配是从堆中分配的。然而,在这个现代,大多数免费商店都使用非二维堆的非常精细的数据结构来实现。

另一答案

什么是堆栈?

堆叠是一堆物体,通常是整齐排列的物体。

Enter image description here

计算体系结构中的堆栈是存储器区域,其中以后进先出的方式添加或移除数据。 在多线程应用程序中,每个线程都有自己的堆栈。

什么是堆?

堆是随意堆积的不整齐的东西。

Enter image description here

在计算体系结构中,堆是动态分配的内存区域,由操作系统或内存管理器库自动管理。 在程序执行期间,会定期分配,释放和重新调整堆上的内存,这可能会导致称为碎片的问题。 当内存对象被分配时,其中的小空间太小而无法容纳额外的内存对象,就会发生碎片。 最终结果是堆空间的百分比不可用于进一步的内存分配。

两者一起

在多线程应用程序中,每个线程都有自己的堆栈。但是,所有不同的线程都将共享堆。 因为不同的线程在多线程应用程序中共享堆,这也意味着线程之间必须有一些协调,这样它们就不会尝试访问和操作堆中的相同内存块。同一时间。

哪个更快 - 堆栈还是堆?为什么?

堆栈比堆快得多。 这是因为在堆栈上分配内存的方式。 在堆栈上分配内存就像向上移动堆栈指针一样简单。

对于刚接触编程的人来说,使用堆栈可能是一个好主意,因为它更容易。 由于堆栈很小,因此当您确切知道数据需要多少内存时,或者如果您知道数据的大小非常小时,则需要使用它。 当你知道你的数据需要大量内存时,或者你不确定需要多少内存(比如动态数组),最好使用堆。

Java Memory Model

alloca

堆栈是存储局部变量(包括方法参数)的存储区域。对于对象变量,这些仅仅是对堆上实际对象的引用(指针)。 每次实例化一个对象时,都会留出一大堆堆内存来保存该对象的数据(状态)。由于对象可以包含其他对象,因此某些数据实际上可以保存对这些嵌套对象的引用。

另一答案

你可以用堆栈做一些有趣的事情。例如,你有像enter image description here这样的函数(假设你可以通过关于它的使用的大量警告),这是一种malloc,它专门使用堆栈而不是堆来存储。

也就是说,基于堆栈的内存错误是我经历过的最糟糕的错误。如果使用堆内存,并且超出了已分配块的范围,则有可能触发段错误。 (不是100%:你的块可能偶然与你先前分配的另一个块连续。)但是由于在堆栈上创建的变量总是相互连续,因此写出越界可以改变另一个变量的值。我了解到,每当我觉得我的程序已经停止遵守逻辑定律时,它可能就是缓冲区溢出。

另一答案

简单地说,堆栈是创建局部变量的地方。此外,每次调用子程序时,程序计数器(指向下一个机器指令的指针)和任何重要的寄存器,有时参数都会被压入堆栈。然后子程序中的任何局部变量被压入堆栈(并从那里使用)。当子程序结束时,所有东西都会从堆栈中弹出。 PC和寄存器数据在弹出时会被放回原处,因此您的程序可以顺利进行。

堆是内存区域动态内存分配由(显式“新”或“分配”调用)组成。它是一种特殊的数据结构,可以跟踪不同大小的内存块及其分配状态。

在“经典”系统中,RAM被布置成使得堆栈指针从内存的底部开始,堆指针从顶部开始,并且它们朝向彼此增长。如果它们重叠,则表示RAM不足。但这不适用于现代多线程操作系统。每个线程都必须有自己的堆栈,这些堆栈可以动态创建。

另一答案

来自WikiAnwser。

Stack

当函数或方法调用另一个函数,该函数又调用另一个函数等时,所有这些函数的执行将保持挂起,直到最后一个函数返回其值。

这个挂起函数调用链是堆栈,因为堆栈中的元素(函数调用)彼此依赖。

在异常处理和线程执行中,堆栈很重要。

Heap

堆只是程序用来存储变量的内存。堆的元素(变量)彼此之间没有依赖关系,并且可以随时随机访问。

另一答案

  • 非常快速的访问
  • 不必显式取消分配变量
  • 空间由CPU有效管理,内存不会碎片化
  • 仅限局部变量
  • 限制堆栈大小(取决于操作系统)
  • 变量无法调整大小

  • 可以全局访问变量
  • 内存大小没有限制
  • (相对)访问速度较慢
  • 无法保证有效利用空间,随着内存块的分配,内存可能会随着时间的推移而变得碎片化,然后被释放
  • 你必须管理内存(你负责分配和释放变量)
  • 可以使用realloc()调整变量的大小
另一答案

好吧,简单而言之,它们意味着有序而不是有序......!

堆栈:在堆栈项目中,事物处于彼此的顶部,意味着要更快,更高效地处理!...

所以总有一个索引指向特定项目,处理速度也会更快,项目之间也存在关联!...

堆:没有订单,处理速度会慢,价值会混乱,没有特定的订单或索引......有随机的,它们之间没有关系......所以执行和使用时间可能会有所不同......

我还创建了下面的图像,以显示它们的外观:

here

另一答案

简而言之

堆栈用于静态内存分配,堆用于动态内存分配,两者都存储在计算机的RAM中。


详细地

堆栈

堆栈是一个“LIFO”(后进先出)数据结构,由CPU非常密切地管理和优化。每次函数声明一个新变量时,它都会被“推”到堆栈上。然后每次函数退出时,该函数推送到堆栈的所有变量都被释放(也就是说,它们被删除)。一旦释放了堆栈变量,该内存区域就可用于其他堆栈变量。

使用堆栈存储变量的优点是可以为您管理内存。您不必手动分配内存,也不必在不再需要时释放内存。更重要的是,因为CPU如此高效地组织堆栈内存,读取和写入堆栈变量的速度非常快。

更多可以找到Valgrind


堆是计算机内存的一个区域,不会自动为您管理,并且不受CPU的严格管理。它是一个更自由浮动的内存区域(并且更大)。要在堆上分配内存,必须使用malloc()或calloc(),它们是内置的C函数。一旦你在堆上分配了内存,你就有责任使用free()在你不再需要它时解除分配该内存。

如果您没有这样做,您的程序将具有所谓的内存泄漏。也就是说,堆上的内存仍然会被搁置(并且不会被其他进程使用)。正如我们将在调试部分中看到的,有一个名为here的工具可以帮助您检测内存泄漏。

与堆栈不同,堆对可变大小没有大小限制(除了计算机明显的物理限制)。堆内存的读取和写入速度稍慢,因为必须使用指针来访问堆上的内存。我们将很快讨论指针。

与堆栈不同,堆上创建的变量可由程序中的任何位置的任何函数访问。堆变量本质上是全局的。

更多可以找到Enter image description here


在堆栈上分配的变量直接存储到存储器中,并且对该存储器的访问非常快,并且在编译程序时处理其分配。当函数或方法调用另一个函数,该函数又调用另一个函数等时,所有这些函数的执行将保持挂起,直到最后一个函数返回其值。堆栈始终以LIFO顺序保留,最近保留的块始终是要释放的下一个块。这使得跟踪堆栈非常简单,从堆栈中释放块只不过是调整一个指针。

在堆上分配的变量在运行时分配其内存并访问此内存有点慢,但堆大小仅受虚拟内存大小的限制。堆的元素彼此之间没有依赖关系,并且可以随时随机访问。您可以随时分配一个块并随时释放它。这使得在任何给定时间跟踪堆的哪些部分被分配或释放变得更加复杂。

Enter image description here

如果您确切地知道在编译之前需要分配多少数据,那么您可以使用堆栈,并且它不会太大。如果您不确切知道运行时需要多少数据,或者需要分配大量数据,则可以使用堆。

在多线程情况下,每个线程都有自己完全独立的堆栈,但它们将共享堆。堆栈是特定于线程的,堆是特定于应用程序的。在异常处理和线程执行中,堆栈很重要。

每个线程都获得一个堆栈,而应用程序通常只有一个堆(尽管为不同类型的分配设置多个堆并不罕见)。

here

在运行时,如果应用程序需要更多堆,它可以从空闲内存分配内存,如果堆栈需要内存,它可以从应用程序的空闲内存分配内存中分配内存。

甚至,更多的细节给予here以上是关于堆栈和堆的内容和位置是什么?的主要内容,如果未能解决你的问题,请参考以下文章

Swift 栈和堆的理解

malloc() |堆栈和堆位置的内存地址长度的差异| C 编程

C++中栈和堆的地址

为啥在 C# 参考文本中引用堆栈和堆?

单片机中栈和堆的区别是啥?

在java中初始化数组时的堆栈和堆内存[重复]