Skip to content

堆和栈有什么区别?

1381字约5分钟

操作系统

2024-09-29

栈和堆之间的区别可能会让很多人感到困惑. 因此, 这里有一份有关栈和堆的问题和答案清单, 我认为非常有帮助.

栈和堆存储在哪里?

它们都存储在计算机的RAM(随机存取存储器)中.

线程如何与栈和堆交互?多线程中栈和堆如何工作?

在多线程应用程序中, 每个线程都有自己的栈. 但是, 所有不同的线程将共享堆. 由于多线程应用程序中的不同线程共享堆, 这也意味着线程之间必须进行某种协调, 以便它们不会同时尝试访问和操作堆中的同一块内存.

对象可以存储在栈上而不是堆上吗?

是的, 对象可以存储在栈中. 如果您在函数内部创建对象而不使用new运算符, 那么这将在栈上创建并存储对象, 而不是在堆上. 假设我们有一个名为 Member 的 C++ 类, 我们想为其创建一个对象. 我们还有一个名为 somefunction() 的函数. 代码如下所示:

void somefunction()
{
/* create an object "m" of class Member
    this will be put on the stack since the 
    "new" keyword is not used, and we are 
   creating the object inside a function
*/
  
  Member m;

} //the object "m" is destroyed once the function ends

因此, 一旦函数运行完成, 或者换句话说, 当它"超出范围"时, 对象m就会被销毁. 一旦函数运行完毕, 栈上用于对象m的内存将被删除.

如果我们想在函数内部的堆上创建一个对象, 那么代码将是这样的:

void somefunction( )
{
/* create an object "m" of class Member
    this will be put on the heap since the 
    "new" keyword is used, and we are 
   creating the object inside a function
*/
  
  Member* m = new Member( ) ;
  
  /* the object "m" must be deleted
      otherwise a memory leak occurs
  */

  delete m; 
}

在上面的代码中, 你可以看到对象m是在函数内部使用new关键字创建的. 这意味着m将在堆上创建. 但是, 由于m是使用new关键字创建的, 这也意味着我们必须自己删除m对象——否则我们最终会遇到内存泄漏.

栈上的内存与堆上的内存相比能持续多长时间?

一旦函数调用运行完成, 栈上专门为该函数调用创建的任何数据都将自动被删除. 堆上的任何数据都将保留在那里, 直到程序员手动删除.

栈的大小可以增长吗? 堆的大小可以增长吗?

栈的大小是固定的 , 不能超过固定大小(尽管有些语言有允许这样做的扩展). 因此, 如果栈上没有足够的空间来处理分配给它的内存, 就会发生栈溢出. 这通常发生在调用大量嵌套函数或存在无限递归调用时.

如果当前堆的大小太小, 无法容纳新的内存, 那么操作系统可以向堆中添加更多内存. 这是堆和栈之间的一个很大的区别.

栈和堆是如何实现的?

实现实际上取决于语言、编译器和运行时栈和堆的实现细节总是会有所不同, 具体取决于所使用的语言和编译器. 但从总体上看, 一种语言中的栈和堆用于完成与另一种语言中的栈和堆相同的任务.

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

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

如何在栈和堆上释放内存?

当变量超出范围时, 栈上的数据会自动释放. 但是, 在 C 和 C++ 等语言中, 存储在堆上的数据必须由程序员使用内置关键字(如freedeletedelete[ ])手动删除. Java 和 .NET 等其他语言使用垃圾收集自动从堆中删除内存, 而无需程序员执行任何操作.

栈和堆可能出现什么问题?

如果栈内存不足, 则称为栈溢出, 并可能导致程序崩溃. 堆可能存在碎片问题, 当堆上的可用内存被存储为不连续(或断开)的块时会发生这种情况. 因为已使用的内存块位于未使用的内存块之间. 当出现过多碎片时, 分配新内存可能是不可能的. 因为即使有足够的内存用于所需的分配, 但一个大块中可能没有足够的内存用于所需的内存量.

我应该使用哪一个——栈还是堆?

对于编程新手来说, 使用栈可能是一个好主意, 因为它更简单. 由于栈很小, 因此当您确切知道数据需要多少内存, 或者您知道数据的大小非常小时, 您会想要使用它. 当你知道数据需要大量内存, 或者您只是不确定需要多少内存(例如动态数组)时, 最好使用堆.