我读了很多关于垃圾回收的文章,几乎所有文章都是讲堆内存。所以我的问题是,“垃圾回收是回收栈内存、堆内存还是两者都回收”。
我读了很多关于垃圾回收的文章,几乎所有文章都是讲堆内存。所以我的问题是,“垃圾回收是回收栈内存、堆内存还是两者都回收”。
它收集堆内存。通常情况下,当执行路径到达作用域的结尾时,栈内存会被自动收集。例如:
void fun()
{
int n; // reservation on the stack as part of the activation record
...
} // returning the stack pointer to where it was before entering the scope
实际上,在像 C++ 这样的语言中,栈分配的变量被称为 auto
变量。
堆内存。
垃圾回收是一种释放不再使用的内存的方法。有时,“不再使用的”部分可能比较棘手。对于栈来说,一旦函数返回,我们可以(除了程序员错误)放心地认为本地变量不再被使用,因此它们会在几乎所有语言/运行时自动释放。
堆栈被称为“堆栈”,正是因为它是一个使用“堆栈策略”(也称为LIFO,即后进先出)进行管理的内存区域。如果不按照“堆栈方式”在堆栈上分配内存,则不会称之为堆栈而是堆。
垃圾回收是为了解决在堆上分配内存(即不能预测哪些部分将首先释放)的问题而发明的。 GC用于内存分配问题,其中堆栈管理不足以满足要求。
栈是后进先出的,因此不需要进行垃圾回收。
--已更正-- 哎呀!
除非您使用的是我们都不知道的分析器,否则堆栈将是主要问题。这是因为大多数人只是按照一个备受赞誉的工具所说的去反应。请看完这篇文章,您会发现大多数指出静态分配内存错误的分析工具通常是正确的。性能分析应该超越简单的泄漏和垃圾收集。
让我以 C 语言为例:
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *am_i_leaking;
am_i_leaking = strdup("Now, that's subjective!");
return 0;
}
char *foo(void)
{
static char bar[1024];
memset(bar, 0, sizeof(bar));
snprintf(bar, sizeof(bar -1), "Do wa diddy diddy dum diddy do");
return bar;
}
你的编译器如何分配内存,这取决于你的编译器。如果你使用它并且可以调整结果,那么你可能有一个有问题的编译器。然而,如果我有100个线程同时进入该函数,那么结果肯定是垃圾,除非我的编译器神奇地弄清楚了我想要什么,并引入了互斥或动态分配,而我不必担心它,此时我们又回到了堆分析。
简而言之,在我们的生命周期中,垃圾收集与堆有关。未来会有一些人尝试着去处理栈并尝试“优化”事情,然后计算这种努力成为一种被一群CEO所需求的解释性语言。
这并不意味着忽略内存错误是一件好事,无论存储器是什么。
栈是您的方法参数和本地变量所在的位置。如果您离开该方法,则堆栈指针会自动递减(或递增,具体取决于特定实现)。这对大多数编程语言都是正确的。
相比之下,垃圾回收仅在堆上工作。
至少在Java中,堆栈会在离开该堆栈帧时自动释放,因此无需垃圾回收。
我是一名Java程序员,所以我没有这个问题,但实际上在C++中,(据我听说)你必须小心处理这个问题,因为你可以在堆栈上分配对象,而当你离开该堆栈帧时,对象将被释放,你不能再使用它等。
你没有引用任何特定的技术,但这种使用在各种编程语言中都很典型。
垃圾回收器仅在托管堆上工作。在单个进程中可能有多个堆,其中一些不会进行垃圾回收。
在堆栈上分配的变量在方法返回时被释放。垃圾回收器将使用这些变量来查找活动引用,但它不会回收内存。