我对此感到疑惑,因为操作系统负责内存管理。为什么编程语言必须实现自己的垃圾收集器?
答案 0 :(得分:8)
操作系统如何知道什么是垃圾?什么不是?
每种编程语言都有其规则来定义数据结构是什么以及何时数据结构被另一个数据结构引用。每种编程语言实现(即编译器,解释器,运行时)都有其表示存储器中的数据结构的方式。垃圾收集器需要知道数据是如何表示的:它需要知道什么是指针,以及指针指向的是什么。
通常,指针是内存中的地址。但是没有办法知道哪个存储器单元包含指针以及哪些存储器单元包含一些非指针数据,这些非指针数据恰好具有正确的位模式作为有效指针。此外,还需要其他信息来了解指针引用的数据的大小。
有保守的垃圾收集器,它假设每个可以解释为指针的存储器单元都是指针。即使这样,垃圾收集器也需要知道指针所指向的数据的开始和停止位置,因此垃圾收集器需要知道编程语言环境使用的内存表示。此外,垃圾收集器必须假设没有隐藏指针(例如,写入磁盘,压缩,......)。
如果允许程序包含任意机器代码(大多数操作系统都是这种情况),则必须将垃圾收集留给每个编程环境。有一些专门的操作系统会强制所有程序使用相同的运行时环境(例如,所有程序都必须在JVM或.NET中运行)并且包含垃圾收集器。
操作系统通常包括特殊形式的垃圾收集器,通常基于引用计数,例如,当打开文件的进程数量减少到0时关闭文件,或者同样用于共享内存区域。答案 1 :(得分:7)
我对此感到疑惑,因为操作系统不负责内存管理吗?
仅在操作系统为程序分配内存的意义上,然后程序决定如何使用自己的内存管理器来使用它。在操作系统中进一步集中内存管理是有问题的,因为它会很慢:程序具有不同的内存访问模式,因此为它们提供所有相同的GC将使程序员更难以使用自定义内存管理模式。例如,不同的语言运行时需要不同的垃圾收集器来支持语言'有效的成语。它还会要求操作系统管理程序中的内存,从而使操作系统设计复杂化。
实际上,从某种意义上说,操作系统已经提供了GC:当程序退出时,典型的操作系统将清理其内存。但只要程序运行,它就负责管理操作系统提供的内存。
编辑:关于什么构成操作系统的其他答案有一些讨论。我考虑过一个狭窄的定义,其中OS是内核,一个为进程提供调度和服务的运行程序。这与您典型的Windows / Linux / Unix桌面/服务器操作系统相匹配。
答案 2 :(得分:3)
垃圾收集需要操作系统知道垃圾是什么,不是垃圾,最简单的方法就是某种类型的安全保障。一些实验性操作系统,例如Es和Singularity,在内核级别提供类型安全的语言运行时:Es中的JavaScript和Singularity中的C#变体。但大多数内核旨在允许运行流行的类型不安全语言(如C ++)中的应用程序。在这种情况下,所有内核都可以回收已终止的进程所占用的内存。
因此,大多数内核将属于特定进程的内存管理委托给语言运行时。所有主要桌面操作系统的默认安装包括多个垃圾收集语言运行时,应用程序可在其中运行。
答案 3 :(得分:1)
垃圾收集将由自己的软件,软件编程或编码进行,但这很复杂,需要开发人员的高级经验。
通常,用C和C ++编写的程序没有像Java或PHP编写的程序那样的自动内存管理。这意味着用C ++编写的程序要求程序员定义软件使用的数据在不再使用时将从内存中删除。
因此,您使用的许多程序都是用C和C ++编写的,大多数情况下内存管理效率不高。运行这些程序时,您的内存将包含许多不再使用的片段,这是程序的失败。我知道的唯一选择是重启PC。
我同意SO本身应该有一些工具来“清理未使用的内存空间”,就像Android(例如Ccleaner)一样。