Windows DLL已重新加载到其首选地址

Windows DLL已重新加载到其首选地址,windows,dll,sysinternals,base-address,Windows,Dll,Sysinternals,Base Address,在Windows Server 2003上,我的应用程序开始需要很长时间才能加载到新安装。我怀疑dll没有加载到它们的首选地址,这需要一些时间(应用程序有100多个dll,包括第三方)我运行了sysinternals listdll实用程序,要求它标记每个已重新定位的dll。奇怪的是,对于列表中的大多数DLL,我得到如下结果: Base Size Path ### Relocated from base of 0x44e90000: 0x44e90000 0x390

在Windows Server 2003上,我的应用程序开始需要很长时间才能加载到新安装。我怀疑dll没有加载到它们的首选地址,这需要一些时间(应用程序有100多个dll,包括第三方)我运行了sysinternals listdll实用程序,要求它标记每个已重新定位的dll。奇怪的是,对于列表中的大多数DLL,我得到如下结果:

Base        Size      Path
  ### Relocated from base of 0x44e90000:
0x44e90000  0x39000   validation.dll
也就是说:它们被标记为重新定位(加载时间似乎肯定支持这一理论),但它们的加载地址仍然是首选地址

一些第三方DLL似乎对此免疫,但总的来说,应用程序加载的大约90%的DLL都会发生这种情况

在Windows7上,似乎唯一标记的DLL是实际移动的DLL,并且加载时间(如预期的)要快得多

这是什么原因造成的?我怎样才能阻止它

编辑:因为它听起来(理论上)像ASLR的效果,我检查了一下,虽然OS DLL确实启用了ASLR,但我们的没有。甚至这些都被重新定位,因此不会占用任何其他DLL的地址。

这是很常见的,设置链接器的/BASE选项经常被忽略,而在DLL增长时维护它是一项令人不愉快的维护任务。这在不同的操作系统版本之间不会很好地重复,它们会在您的DLL之前加载不同的DLL,这可能会在其中一个版本上强制重新定位,但在另一个版本上不会。此外,单个重新定位可能会导致所有后续DLL上的一系列强制重新定位

在现代机器上,这明显影响加载时间有点遥远。重新定位本身非常快,只是一个内存操作。您确实为重新定位的DLL使用的内存得到提交而付费。由于原始DLL文件不再适合在调出时重新加载代码,因此它现在由分页文件支持,这是必需的。如果需要增长以适应提交大小,则需要花费时间。这并不常见

加载时间中更常见的问题是磁盘驱动器的速度。一个问题当您有很多DLL时,它们需要在冷启动时位于磁盘上。有了100个DLL,这很容易花费5秒钟。如果在终止程序并再次启动时没有看到延迟,则应怀疑冷启动问题。这是一个良好的开端,DLL已经存在于文件系统缓存中,因此不必再次找到。解决冷启动问题需要更好的硬件,SSD很好。或者机器正在学习您的使用模式,以便SuperFetch在您启动程序之前为您预取DLL

总之,如果您怀疑有重定基址的问题,那么您需要创建自己的内存映射,以找到不需要重新定位的良好基址。您需要一个良好的起点,了解DLL的加载顺序和大小。你可以从VS调试器那里得到。“输出”窗口显示加载顺序,“调试+窗口+模块”窗口显示DLL大小。链接器支持在/base选项中为基址指定一个.txt文件,这是最好的方法,这样您就不必在代码不断增长的同时不断修改单个/base值。

这很常见,设置链接器的/BASE选项经常被忽略,而在DLL增长时维护它是一项令人不快的维护任务。这在不同的操作系统版本之间不会很好地重复,它们会在您的DLL之前加载不同的DLL,这可能会在其中一个版本上强制重新定位,但在另一个版本上不会。此外,单个重新定位可能会导致所有后续DLL上的一系列强制重新定位

在现代机器上,这明显影响加载时间有点遥远。重新定位本身非常快,只是一个内存操作。您确实为重新定位的DLL使用的内存得到提交而付费。由于原始DLL文件不再适合在调出时重新加载代码,因此它现在由分页文件支持,这是必需的。如果需要增长以适应提交大小,则需要花费时间。这并不常见

加载时间中更常见的问题是磁盘驱动器的速度。一个问题当您有很多DLL时,它们需要在冷启动时位于磁盘上。有了100个DLL,这很容易花费5秒钟。如果在终止程序并再次启动时没有看到延迟,则应怀疑冷启动问题。这是一个良好的开端,DLL已经存在于文件系统缓存中,因此不必再次找到。解决冷启动问题需要更好的硬件,SSD很好。或者机器正在学习您的使用模式,以便SuperFetch在您启动程序之前为您预取DLL


总之,如果您怀疑有重定基址的问题,那么您需要创建自己的内存映射,以找到不需要重新定位的良好基址。您需要一个良好的起点,了解DLL的加载顺序和大小。你可以从VS调试器那里得到。“输出”窗口显示加载顺序,“调试+窗口+模块”窗口显示DLL大小。链接器支持在/base选项中为基址指定一个.txt文件,这是最好的方法,这样您就不必在代码不断增长的同时不断修改单个/base值。

我们为所有DLL指定了基址。“而且,一次重新定位可能会导致所有后续DLL上的一系列强制重新定位。”就是这样:它们都不会重新定位到不同的地址—如果您相信Process Explorer的加载地址(以及上面列出的DLL输出中的基地址),它们都位于首选地址。有些事情需要很长时间,DLL被标记为重定基址,但它们都在我们要求它们的位置……好吧,很好,世界是有意义的。很明显,您现在对我记录的“更常见的问题”更感兴趣。使用一个真正的调试器来追踪那些脆弱的