Dettagli tecnici
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
Questo sintomo di per sé non ha nulla a che fare con basi di immagini di eseguibili, sezioni di memoria condivisa di Cygwin danneggiate, versioni in conflitto di DLL ecc.
È il codice Cygwin che non riesce a allocare un grosso pezzo di memoria di ~ 5 MB per il suo heap a questo indirizzo fisso 0x68570000, mentre apparentemente era disponibile solo un buco di ~ 2,5 MB. Il codice rilevante può essere visto nella sorgente msysgit .
Perché quella parte dello spazio degli indirizzi non è libera?
Ci possono essere molte ragioni. Nel mio caso c'erano altri moduli caricati su un indirizzo in conflitto:
L'ultimo indirizzo sarebbe circa 0x68570000 + 5 MB = 0x68C50000, ma ci sono queste DLL relative a WOW64 caricate da 0x68810000 in poi, che bloccano l'allocazione.
Ogni volta che è presente una DLL condivisa, Windows in generale tenta di caricarla nello stesso indirizzo virtuale in tutti i processi per salvare l'elaborazione del trasferimento. È solo una sfortuna che stavolta questi componenti di sistema siano stati caricati in qualche modo in un indirizzo contrastante .
Perché c'è Cygwin nel tuo Git?
Perché Git è una ricca suite composta da alcuni comandi di basso livello e molte utili utility, e per lo più sviluppata su sistemi simili a Unix. Per essere in grado di costruirlo ed eseguirlo senza una massiccia riscrittura, è necessario almeno un ambiente simile a Unix parziale.
Per riuscirci, le persone hanno inventato MinGW e MSYS, un set minimo di strumenti di build per sviluppare programmi su Windows in modo simile a Unix. MSYS contiene anche una libreria condivisa, questa msys-1.0.dll
, che aiuta con alcuni dei problemi di compatibilità tra le due piattaforme durante il runtime. E molte parti sono state prese da Cygwin, perché qualcuno doveva già risolvere gli stessi problemi lì.
Quindi non è Cygwin, è la DLL di runtime di MinGW che si comporta in modo strano qui.
In Cygwin, questo codice è cambiato molto da quando è presente in MSYS 1.0 - l'ultimo messaggio di commit per quel file dice "Importa Cygwin 1.3.4", che è del 2001!
Sia l' attuale Cygwin che la nuova versione di MSYS - MSYS2 - hanno già una logica diversa, che si spera sia più solida. Sono solo vecchie versioni di Git per Windows che sono state ancora costruite usando il vecchio sistema MSYS rotto.
Soluzioni pulite:
- Installa Git per Windows 2 - è costruito con il nuovo MSYS2 , correttamente gestito e ha anche molte nuove funzionalità, molte correzioni di bug, miglioramenti della sicurezza e così via. Se possibile, si consiglia anche di utilizzare la versione a 64 bit . Ma la soluzione alternativa di rebase viene eseguita automaticamente dietro le quinte per i sistemi a 32 bit, quindi anche le probabilità che si verifichi il problema dovrebbero essere inferiori.
- Il semplice riavvio del computer per pulire lo spazio degli indirizzi (caricamento di questi moduli in un indirizzo casuale diverso) potrebbe funzionare, ma in realtà, basta aggiornare a Git per Windows 2 per ottenere le correzioni di sicurezza se non altro.
Soluzioni Hacky:
- Il cambiamento a
PATH
volte può funzionare perché potrebbero esserci versioni diverse msys-1.0.dll
in diverse versioni di Git o altre applicazioni basate su MSYS, che forse usano indirizzi diversi, dimensioni diverse di questo heap ecc.
- Rebasing
msys-1.0.dll
potrebbe essere una perdita di tempo, perché 1) essendo una DLL, ha già informazioni di riposizionamento e 2) "in qualsiasi versione del sistema operativo Windows non vi è alcuna garanzia che una (...) DLL venga sempre caricata nello stesso spazio degli indirizzi" comunque ( fonte ). L'unico modo in cui ciò può essere d'aiuto è se lo msys-1.0.dll
stesso si carica all'indirizzo in conflitto che sta tentando di utilizzare. Apparentemente a volte è così, poiché è quello che fanno i ragazzi di Git per Windows automaticamente sui sistemi a 32 bit .
- Considerando i risultati di cui sopra, originariamente ho applicato una patch
msys-1.0.dll
binaria al binario per utilizzare un valore diverso _cygheap_start
e ciò ha risolto immediatamente il problema.