当对象在内存中移动时,指针如何保持有效?

Avi*_*ohn 6 c memory pointers

想象一下CI在堆上分配两个结构.其中一个结构有一个字段,其中包含指向另一个结构的指针.

据我所知,堆中的数据可能会移动,因此事物的地址会发生变化.例如,可能会发生堆上的碎片整理,将第二个结构移动到堆中的其他位置.

这有助于理解我所说的内容 https://en.m.wikibooks.org/wiki/Memory_Management/Memory_Compacting

这个结构的重点现在是错误的(即保持错误的内存地址).

我并不是说这个问题是C的特定问题,而是更一般的问题:在任何时候,平台都可能决定改变一切.指针如何保持有效?

fan*_*ton 14

这里的关键概念是虚拟内存.您的指针不指向物理地址,而是指向进程虚拟地址空间中的虚拟地址.你说的是正确的,数据可能会被移动,甚至交换到磁盘,然后再次映射到物理内存到另一个帧,但指针指向的虚拟地址始终保持不变.


tre*_*tcl 5

C 标准不允许实现(自发地)以一种会使现有指针无效的方式移动事物。可能存在对堆进行“碎片整理”的实现,但我不知道有任何实现。

我说“自发”是因为realloc()在您的代码中调用实际上可能会导致对象移动;这就是为什么realloc返回一个指针。如果返回的指针realloc与原始指针不同,则原始指针(以及为其别名的任何指针)无效。但这是您必须在自己的代码中跟踪的内容。

托管语言(Java、C#、Python 等)可能会(也可能不会)通过添加额外的间接级别和/或跟踪指向堆的指针来处理堆碎片。这样,当 X 移动到不同的位置时,语言运行时可以更新所有指向对象 X 的指针。这将由垃圾收集系统处理。

C 实现提供垃圾收集器会有些不寻常,并且可能无法以符合标准的方式完成,因为您可以(安全地)使用指针执行所有操作。因此,您的问题的前提是堆可能会自发地被实现进行碎片整理,这是无效的。