垃圾收集器在这做什么?

时间:2010-06-19 20:32:12

标签: c memory-management garbage-collection

我在另一个帖子中看到了这段代码

void foo {
  int *n = malloc(sizeof(int)); 
  *n = 10; 
  n++;
  printf("%d", *n);
}

这里的错误是显而易见的。 n未被解除引用。 有内存泄漏。 我们假设有一个垃圾收集器在这里工作。我们的初始值n的引用计数现在为零,因为n不再引用它。所以它是垃圾并返回。但是n指向的新位置怎么样?从技术上讲,这个记忆区域尚未分配。那么引用计数会在这里增加吗?

3 个答案:

答案 0 :(得分:1)

正确实现的垃圾收集器的工作方式如下:

int *pi = malloc(sizeof int);
*pi = 10;

这里的一切都很好。

pi++;

此语句允许pi指向已分配的int,这是ISO C99标准明确允许的(参见6.5.6p7,6.5.6p8)。稍后在代码中,可能有pi--,因此仍然可以访问已分配的int。或者可以通过表达式pi[-1]访问它,此时此表达式完全有效。

pi = NULL;

此时,无法再访问已分配的int,因此垃圾收集器可能会收集内存。

总结:所有指向对象开头,指向该对象中间某处或该对象后面位置的指针都可用于访问该对象。因此,如果内存中存在这样的值,则不得对该对象进行垃圾回收。

答案 1 :(得分:1)

C垃圾收集器不执行引用计数。它们通常是标记扫描,它们在块上运行,而不是单个字节。在您的示例中,gc将标记块,而不是地址。即便如此,您问题的核心仍然有效:

标记阶段到达“坏”指针时会做什么?
保守的收集器只是忽略它。将收集初始malloc中的内存。

答案 2 :(得分:0)

我改变了主意;我想是的。问题是这样的代码:

int* n = malloc(sizeof(int));
n++;
int* o = n;
int* p = n;
n = malloc(sizeof(int));

现在有三个对n指向的内存的引用,但垃圾收集器只看到一个。尽管存在n = NULL;o指针,但执行p会导致清理。像这样的指针灵活性是C垃圾收集器如此困难的主要原因;我不确定在C中是否有可能有一个完美的垃圾收集器,因为你可以有指针,其地址直到运行时才知道