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