Szczegóły techniczne
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
Ten objaw sam w sobie nie ma nic wspólnego z bazami obrazów plików wykonywalnych, uszkodzonymi sekcjami pamięci wspólnej Cygwin, sprzecznymi wersjami bibliotek DLL itp.
To kod Cygwina, który nie przydziela ok. 5 MB dużej pamięci dla swojego sterty pod tym stałym adresem 0x68570000, podczas gdy najwyraźniej dostępna była tam tylko dziura o wielkości ok. 2,5 MB. Odpowiedni kod można zobaczyć w źródle msysgit .
Dlaczego ta część przestrzeni adresowej nie jest wolna?
Może być wiele przyczyn. W moim przypadku były to inne moduły załadowane pod adres powodujący konflikt:
Ostatni adres powinien wynosić około 0x68570000 + 5 MB = 0x68C50000, ale niektóre biblioteki DLL związane z WOW64 są ładowane od 0x68810000 w górę, co blokuje przydział.
Ilekroć istnieje wspólna biblioteka DLL, Windows ogólnie próbuje załadować ją pod tym samym adresem wirtualnym we wszystkich procesach, aby zaoszczędzić trochę przetwarzania relokacji. To tylko kwestia pecha, że te elementy systemu, ale jakoś załadowanego w konflikcie adres ten czas .
Dlaczego w twoim Git jest Cygwin?
Ponieważ Git jest bogatym pakietem składającym się z kilku poleceń niskiego poziomu i wielu przydatnych narzędzi i głównie opracowanych na systemach uniksopodobnych. Aby móc go zbudować i uruchomić bez masywnego przepisywania, potrzebuje przynajmniej częściowego środowiska uniksowego.
Aby to osiągnąć, ludzie wymyślili MinGW i MSYS - minimalny zestaw narzędzi do budowania programów w systemie Windows w sposób podobny do Uniksa. MSYS zawiera również bibliotekę współdzieloną msys-1.0.dll
, która pomaga w niektórych problemach ze zgodnością między dwiema platformami w czasie wykonywania. Wiele z nich zostało zaczerpniętych od Cygwina, ponieważ ktoś już musiał rozwiązać te same problemy.
Więc to nie Cygwin, to biblioteka uruchomieniowa MinGW, która zachowuje się tutaj dziwnie.
W Cygwin ten kod faktycznie się bardzo zmienił od czasu, co jest w MSYS 1.0 - ostatnia wiadomość zatwierdzenia dla tego pliku mówi „Importuj Cygwin 1.3.4”, która pochodzi z 2001 roku!
Zarówno obecny Cygwin, jak i nowa wersja MSYS - MSYS2 - mają już inną logikę, która, mam nadzieję, jest bardziej niezawodna. To tylko stare wersje Git dla Windows, które zostały zbudowane przy użyciu starego, zepsutego systemu MSYS.
Czyste rozwiązania:
- Zainstaluj Git dla Windows 2 - jest on zbudowany z nowym, odpowiednio utrzymanym MSYS2, a także ma wiele nowych funkcji, wiele poprawek błędów, ulepszeń bezpieczeństwa i tak dalej. Jeśli to w ogóle możliwe, zaleca się również użycie wersji 64-bitowej . Ale obejście rebase jest wykonywane automatycznie w tle dla systemów 32-bitowych, więc szanse na wystąpienie problemu powinny być również niższe.
- Ponowne uruchomienie komputera w celu wyczyszczenia przestrzeni adresowej (ładowanie tych modułów pod innym losowym adresem) może działać, ale tak naprawdę wystarczy uaktualnić do Git dla systemu Windows 2, aby uzyskać poprawki zabezpieczeń, jeśli nic więcej.
Hacky rozwiązania:
- Zmiana
PATH
może czasami działać, ponieważ mogą istnieć różne wersje msys-1.0.dll
różnych wersji Git lub innych aplikacji opartych na MSYS, które mogą używać innego adresu, innego rozmiaru stosu itp.
- Ponowne uruchomienie
msys-1.0.dll
może być stratą czasu, ponieważ 1) będąc biblioteką DLL, ma już informacje o relokacji i 2) „w żadnej wersji systemu operacyjnego Windows nie ma gwarancji, że (...) biblioteka DLL zawsze będzie ładować w tej samej przestrzeni adresowej” w każdym razie ( źródło ). Jedynym sposobem, w jaki może to pomóc, jest to, że msys-1.0.dll
sam ładuje się pod adres powodujący konflikt, którego następnie próbuje użyć. Najwyraźniej czasami tak jest, ponieważ właśnie tak robią faceci Git dla Windows w systemach 32-bitowych .
- Biorąc pod uwagę powyższe ustalenia, pierwotnie plik binarny załatałem
msys-1.0.dll
plik binarny, aby użyć innej wartości _cygheap_start
i to natychmiast rozwiązało problem.