没有垃圾收集器的编程语言:垃圾去哪儿了?

ale*_*asa 1 c garbage-collection dynamic-memory-allocation

我目前正在研究算法和高级数据结构:因为我熟悉 C 并且它确实在实现和指针使用之上提供了很好的控制水平,我正在使用它来测试到目前为止对主题的理解。

在测试需要动态事物(如列表和树)的结构时,我问自己:由于 C 没有垃圾收集器,如果我不调用 free() 函数来释放动态分配的所有变量,那在哪里记忆去?

其他相关问题包括(抱歉误用了一些术语,我在低级抽象方面没有太多经验):

  • 编译器是使用实际的硬盘驱动器资源(例如驱动器的 x 记录中的变量)还是“实例化”一部分虚拟内存来编译和运行我的程序?

  • 我的硬盘中是否有很多列表、树和图形,所有这些都涉及从 0 到 100 的计数或字符串“abcd”和“qwerty”?

  • 操作系统是否将所述数据识别为垃圾,或者在我格式化驱动器之前我一直被这些垃圾困住?

我真的很好奇,我从来没有低于 C 的抽象级别。

Bas*_*tch 5

因为 C 没有垃圾收集器,如果我不调用 free() 函数来释放我动态分配的所有变量,那么内存去哪里了?

这不是(也不能真的)由C11标准定义(阅读n1570)。

但是,让我们假设您在某个熟悉的操作系统(如 Linux 或 Windows 或 MacOSX)上运行由某个 C 编译器生成的可执行文件。实际上,您正在运行一些具有虚拟地址空间的进程

操作系统内核虚拟内存分页子系统会将虚拟地址空间中有用的页面——驻留集大小——放入 RAM 中并配置MMU;阅读有关需求分页抖动以及页面缓存页面错误的信息

当该进程终止时(通过正常退出或某些异常情况,例如分段错误),操作系统将释放进程使用的所有资源(包括该进程的虚拟地址空间)。

阅读操作系统:三个简单的部分了解更多信息。

但是,如果您没有任何操作系统,或者您的操作系统或处理器不支持虚拟内存(想想一些Arduino板),事情可能会有很大不同。阅读有关未定义行为运行时系统的信息

在 Linux 上,您可以使用proc(5)查询 pid 为 1234 的进程的地址空间。在终端中运行cat /proc/1234/maps或使用pmap(1)。从进程内部,读取/proc/self/maps为顺序文件。看到这个

您还可以研究开源标准库的源代码,如GNU libc(在 Linux上的syscalls(2)以上)或musl-libc,或使用strace(1)来了解完成了哪些系统调用。