除了提供在运行时加载/卸载方法或函数的能力的 Dll 概念之外,我想知道编译器是否会说类似这样的话,好的,因为代码的这个特定部分在代码段中占用了大量空间并且是在程序执行期间的这一点之后永远不会再次使用,最好生成一些代码以在程序执行期间到达该特定点后卸载该部分代码段,以便代码段占用的整体空间变得更小。这只是虚构的事情还是可能发生?
4 回答
当然。有一种称为覆盖的技术,可以在不同的时间将不同的代码加载到同一位地址空间中。有时它是手动完成的,有时编译器会提供帮助。有时加载是在软件中完成的,有时是在硬件中完成的(使用地址多路复用,例如,在启动期间,一位地址空间从 ROM 芯片读取,但在启动后它切换到地址 RAM 或不同的 ROM)。
当计算机内存较少时,覆盖更为常见,例如在 DOS 的早期,您最多只有 640K,但通常甚至没有。如今,它仍然适用于内存和/或地址空间非常宝贵的嵌入式系统。
编译器可以做它想做的任何事情,只要不违反标准。如果它能够确定代码不再被调用,它可以完全放弃它。
如果需要,它甚至可以用一个更小的存根函数来替换它,该函数会重新加载代码。
但是您不太可能在现代操作系统中看到这一点,因为操作系统本身在幕后提供了该功能。
操作系统(至少是常见的)将在内存不足时换出您的物理页面,并且在需要它们之前不会重新加载它们(通常是在尝试访问它们时出现页面错误)。
是的,Windows 设备驱动程序使用这种技术。LE 文件格式将某些代码段标记为可丢弃。操作系统也可以在某些时候做出这样的决定,以换出长时间未使用的代码段。
然而,严格来说,这不是编译器可以玩弄的领域。影响这一点的主要是链接器/加载器/操作系统。
我不知道执行此操作的编译器,但没有禁止它的规则。如果编译器可以证明这样做不会改变程序的语义,那么在 as-if 规则下是允许的。
然而,这通常不是必需的,因为未使用的代码已经作为与虚拟内存相关的页面文件机制的一部分被换出。(而且因为您可能只会节省几 KB 的内存空间)