我在另一个帖子中看到了这段代码
void foo {
int *n = malloc(sizeof(int));
*n = 10;
n++;
printf("%d", *n);
}
这里的错误是显而易见的。 n
未被解除引用。
有内存泄漏。
我们假设有一个垃圾收集器在这里工作。我们的初始值n
的引用计数现在为零,因为n
不再引用它。所以它是垃圾并返回。但是n
指向的新位置怎么样?从技术上讲,这个记忆区域尚未分配。那么引用计数会在这里增加吗?
答案 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中是否有可能有一个完美的垃圾收集器,因为你可以有指针,其地址直到运行时才知道