据我所知,所有进程都在自己的虚拟地址空间内运行。如果进程调用malloc,OS将从程序拥有的堆中分配一些区域,并返回一个虚拟地址而不是真实物理地址的地址。由于堆由程序拥有,为什么OS不能回收程序员没有释放的内存?
虚拟地址空间分别用于每个程序,因此程序没有方法来销毁其他程序拥有的数据。我是对的吗?
如果程序访问其他程序拥有的随机地址,则会发生段错误。但是,为什么程序访问以前自己释放的地址时没有错误发生?
答案 0 :(得分:2)
由于堆由程序拥有,为什么OS不能回收程序员没有释放的内存?
假设您在此处执行虚拟内存,操作系统将回收终止时未被程序释放的任何内存。对于短期计划,这不是问题。然而,并非所有系统都具有虚拟内存(想想奇怪的CPU上的嵌入式编程)。对于长时间运行的程序,在程序运行时泄漏内存可能不好。
虚拟地址空间分别用于每个程序,因此程序没有方法来销毁其他程序拥有的数据。我是对的吗?
是
如果程序访问其他程序拥有的随机地址,则会发生段错误。但是,为什么程序访问以前自己释放的地址时没有错误发生?
这取决于。你正在运行什么操作系统,你正在使用哪个分配器,内存块所在的位置以及它的大小都与实际内存的释放有关。简而言之,操作系统会为您的应用程序分配固定大小的内存页面。您的运行时库将malloc请求的内存映射到OS提供的页面。在释放位于其中的所有内存块之前,页面不会释放回操作系统。一些分配器一旦被分配就会保留页面,假设您稍后将再次需要它们。您只会尝试访问不属于您的程序的页面内存的段错误,因为它从未首先分配,或者因为它已被释放回操作系统。
答案 1 :(得分:2)
操作系统无法回收未被正在运行的程序(进程)释放的内存,因为它(操作系统)不知道进程是否仍在使用该内存。这正是释放行为的目的 - 通知操作系统不再使用内存。当然,操作系统可以在程序终止后回收程序的内存。
是的,一个进程不能轻易破坏(甚至修改)另一个进程的地址空间。进程彼此隔离(这是一件好事)并且为了使一些交互成为可能,程序员必须采用一些进程间通信(或IPC)的方法,例如,共享内存,管道,信号等。
实际上,访问以前释放的内存区域 会导致程序崩溃。但通常情况下通过操作系统检测这种错误并不便宜,因此一般都没有。