技术细节
0 [main] us 0 init_cheap: VirtualAlloc pointer is null, Win32 error 487
AllocationBase 0x0, BaseAddress 0x68570000, RegionSize 0x2A0000, State 0x10000
PortableGit\bin\bash.exe: *** Couldn't reserve space for cygwin's heap, Win32 error 0
此症状本身与可执行文件的映像库,Cygwin的共享内存部分损坏,DLL的版本冲突等无关。
Cygwin代码无法在此固定地址0x68570000为其堆分配约5 MB的大内存块,而那里显然只有约2.5 MB的空洞。相关代码可以在msysgit源代码中看到。
为什么地址空间的那部分不空闲?
可能有很多原因。就我而言,这是在冲突的地址处加载了其他一些模块:
最后一个地址约为0x68570000 + 5 MB = 0x68C50000,但是从0x68810000向上加载的这些与WOW64相关的DLL阻止了分配。
只要有共享的DLL,Windows通常都会尝试在所有进程中将其加载到相同的虚拟地址,以节省一些重定位处理。不幸的是,这些系统组件这次以某种方式加载到了一个有冲突的地址。
为什么您的Git中存在Cygwin?
因为Git是一个丰富的套件,由一些底层命令和许多有用的实用程序组成,并且大多数是在类Unix系统上开发的。为了能够在不进行大量重写的情况下构建并运行它,它至少需要部分类似Unix的环境。
为此,人们发明了MinGW和MSYS-一套最小的构建工具,用于以类似Unix的方式在Windows上开发程序。MSYS还包含一个共享库,此msys-1.0.dll
,它可以解决运行时两个平台之间的一些兼容性问题。而且其中很多部分都取自Cygwin,因为有人必须在那里解决相同的问题。
因此,这不是Cygwin,这是MinGW的运行时DLL引起的。
在Cygwin中,此代码实际上已发生了很大变化,因为MSYS 1.0中的内容已更改-该文件的最后一条提交消息为“ Import Cygwin 1.3.4”,这是从2001年开始的!
无论当前的Cygwin和MSYS的新版本 - MSYS2 -已经到位不同的逻辑,这是希望更稳健。这只是Git for Windows的旧版本,仍然使用旧的损坏的MSYS系统构建。
清洁解决方案:
- 安装适用于Windows 2的Git-它是用正确维护的新MSYS2构建的,还具有许多新功能,大量错误修复,安全性改进等。如果可能的话,也建议使用64位版本。但是对于32位系统,在后台自动执行了变基解决方法,因此,在那里发生问题的机会也应该更低。
- 只需重新启动计算机以清理地址空间(将这些模块加载到其他随机地址)可能会起作用,但实际上,只需升级到Windows 2的Git即可获得安全修复程序。
hacky解决方案:
- 更改
PATH
有时可以起作用,因为msys-1.0.dll
不同版本的Git或其他基于MSYS的应用程序中可能存在不同的版本,它们可能使用不同的地址,此堆的不同大小等。
- 重新设置基准
msys-1.0.dll
可能会浪费时间,因为1)作为DLL,它已经具有重定位信息,以及2)“在任何版本的Windows OS中,都无法保证(...)DLL总是会在相同的地址空间加载”无论如何(来源)。唯一有帮助的方法是,如果msys-1.0.dll
自身加载在要使用的冲突地址上。显然有时候是这样,因为Windows的Git正是在32位系统上自动执行的操作。
- 考虑到上述发现,我最初对二进制文件进行了修补,
msys-1.0.dll
以对二进制文件使用其他值,_cygheap_start
然后立即解决了该问题。