Assembly 谁清洁用于存储堆栈的ram?

Assembly 谁清洁用于存储堆栈的ram?,assembly,operating-system,Assembly,Operating System,据我所知,我创建的每个变量都存储在内存中(ram或页面文件idc) 因此,当我将一个变量存储在一个特定的虚拟地址中时,它实际上会存储在真实内存中的某个地方。 据我所知,应用程序不会按字面上的意思清理堆栈——就像去那些地址并将所有内容设置为零一样,它只会递增/递减堆栈指针,而另一个函数使用的内存稍后可能会被另一个函数重新使用。这就是我们创建局部变量时需要初始化它的原因 因此,应用程序本身不会转到ram中的那些地址,并将其再次置零,所以我的问题是谁会这样做?因此下一个过程将能够再次使用这些确切的ra

据我所知,我创建的每个变量都存储在内存中(ram或页面文件idc)

因此,当我将一个变量存储在一个特定的虚拟地址中时,它实际上会存储在真实内存中的某个地方。 据我所知,应用程序不会按字面上的意思清理堆栈——就像去那些地址并将所有内容设置为零一样,它只会递增/递减堆栈指针,而另一个函数使用的内存稍后可能会被另一个函数重新使用。这就是我们创建局部变量时需要初始化它的原因


因此,应用程序本身不会转到ram中的那些地址,并将其再次置零,所以我的问题是谁会这样做?因此下一个过程将能够再次使用这些确切的ram地址。

在同一个程序中,通常没有人清理。堆上新分配的内存和堆栈上新的局部变量可以包含旧数据(如果没有初始化)。如果你不小心初始化的东西,它可能会导致间歇性的错误或被黑客揭露“秘密”数据


启动新程序时,操作系统应负责清除内存。这通常内置于分页系统中:当您请求页面时,应该得到零1。但是操作系统之间的细节差别很大。

在评论中进行了长时间的讨论之后,我认为一些总结性的答案对于这个问题实际上是有意义的(我还认为这个问题并没有那么糟糕——值得投反对票,毕竟你问的是关于特定编程概念的问题,只是有点误解,这可能会让人恼火,但对我来说,这看起来像是关于编程的问题)

首先,操作系统在其内部结构中跟踪已用/可用内存,存储指针/地址范围等内容,处理内存的“页面”而不是单个字节。因此,如果在操作系统内部数据中跟踪物理地址范围0x10000-0x1fff的内存,则操作系统对内存的实际内容不感兴趣“free”,它是免费的。字节的内容无关紧要。如果某个进程占用了该内存区域,操作系统会在其内部数据中跟踪该内存区域,因此在该进程终止时,它会将该区域标记为“free”,即使进程在终止前明确没有释放它

实际上,由于性能原因,操作系统通常不会在分配请求时清除内存(尽管我*猜测*一些经过安全加固的操作系统可能会在每个终止的进程之后清除RAM,只是为了确保将来不会有恶意或敏感的内容泄漏到下一个重用相同物理内存的进程).如果应用程序是用保证新分配内存被清除的语言编写的,则该语言运行库有责任提供该功能

例如C和C++不保证零内存(再次性能原因,清除需要时间),但它们在libc运行时代码中有堆内存管理器代码,添加到从C源代码编译的每个应用程序中,并使用默认库和运行时。堆管理器将操作系统中的空闲内存分配到更大的块中,然后为用户代码对其进行微管理,支持

new/delete/malloc/free
,这实际上不需要修改直接指向OS内存管理器,这就是内部C运行时在耗尽其当前可用内存池时将执行的操作

因此,不需要零值来回收操作系统的内存,它只需要“零值”其内部数据,即RAM的哪些部分正在被使用以及由哪个进程使用

这个操作系统内存管理器代码可能并不琐碎(我从不费心检查实际的实现,但如果你真的喜欢它,可以读一些关于操作系统体系结构的书,还可以研究当前操作系统的源代码),但我猜在原则上启动它时,会映射可用的物理内存,将其划分为不同的区域(有些对用户代码是不受限制的,有些范围是内存映射的I/O设备,因此除了设备的特定驱动程序之外,它们可能对每个人都是不受限制的,通常最大的块是用户应用程序的“空闲”内存),并保留类似于可用内存“页面”列表或操作系统希望管理的任何粒度的内容

因此,谁来清理RAM(和其他资源)-在终止某个进程时,操作系统以及好的操作系统的设计应确保它能够通过该终止进程检测到所有阻塞的资源,并将其回收(无需进程代码本身的配合)。对于较旧的操作系统,这一部分有点缺陷并不少见,操作系统会随着时间的推移不断耗尽某些类型的资源,需要定期重新启动,但任何可靠的操作系统(如大多数UNIX系列操作系统)都可以运行数年而不受干预或泄漏任何信息

为什么我们有垃圾收集器和其他内存管理方法:

因为作为应用程序的程序员,你决定应用程序将使用多少资源。如果你的应用程序将一直在后台运行并分配新资源,而不释放它们,那么最终将耗尽操作系统的可用资源,影响整个机器的性能

但通常在编写应用程序时,您不想对内存进行微管理,因此,如果您在一个位置分配100字节,在另一个位置再分配100字节,那么您就不再需要它们了,但您需要200字节,您可能不想编写复杂的代码来重用以前分配的中断的100+100字节,在大多数应用程序中编程语言让他们的内存管理器通过
free/delete
收集这些早期分配更简单(例如:在C/C++中,除非您使用自己的内存分配器或垃圾收集器),在Java中,您只需删除所有已知的实例引用,GC就会计算出该内存