Технические подробности
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, которому не удается выделить большой кусок памяти размером ~ 5 МБ для его кучи по этому фиксированному адресу 0x68570000, в то время как там, очевидно, была доступна только дыра размером ~ 2,5 МБ. Соответствующий код можно увидеть в источнике msysgit .
Почему эта часть адресного пространства не свободна?
Там может быть много причин. В моем случае это были некоторые другие модули, загруженные по конфликтующему адресу:
Последний адрес будет около 0x68570000 + 5 МБ = 0x68C50000, но есть эти связанные с WOW64 библиотеки DLL, загруженные с 0x68810000 и выше, которые блокируют выделение.
Всякий раз, когда есть какая-то общая DLL, Windows в общем пытается загрузить ее по одному и тому же виртуальному адресу во всех процессах, чтобы сохранить некоторую обработку перемещения. Просто неудача в том, что эти системные компоненты каким-то образом были загружены по конфликтующему адресу в этот раз .
Почему в вашем Git есть Cygwin?
Потому что Git - это богатый пакет, состоящий из команд низкого уровня и множества полезных утилит, и в основном разработанный на Unix-подобных системах. Для того, чтобы его можно было собрать и запустить без масштабного переписывания, ему нужна хотя бы частичная Unix-подобная среда.
Для этого люди изобрели MinGW и MSYS - минимальный набор инструментов для сборки программ для Windows в стиле Unix. MSYS также содержит общую библиотеку, msys-1.0.dll
которая помогает с некоторыми проблемами совместимости между двумя платформами во время выполнения. И многое из этого было взято из Cygwin, потому что кто-то уже должен был решать те же проблемы там.
Так что это не Cygwin, это DLL-библиотека времени выполнения MinGW, которая ведет себя странно.
В Cygwin этот код на самом деле сильно изменился по сравнению с MSYS 1.0 - в последнем сообщении о фиксации для этого файла указано «Import Cygwin 1.3.4», начиная с 2001 года!
Как текущая версия Cygwin, так и новая версия MSYS - MSYS2 - уже имеют разную логику, которая, как мы надеемся, является более надежной. Это только старые версии Git для Windows, которые все еще были созданы с использованием старой сломанной системы MSYS.
Чистые решения:
- Установите Git для Windows 2 - он построен с новым, должным образом поддерживаемым MSYS2, а также имеет много новых функций, множество исправлений ошибок, улучшений безопасности и так далее. Если это вообще возможно, рекомендуется также использовать 64-битную версию . Но обходной путь rebase выполняется автоматически за кулисами для 32-разрядных систем, поэтому вероятность возникновения проблемы также должна быть ниже.
- Простая перезагрузка компьютера для очистки адресного пространства (загрузка этих модулей по другому случайному адресу) может сработать, но на самом деле просто обновите Git для Windows 2, чтобы получить исправления безопасности, если ничего больше.
Хакерские решения:
- Изменение
PATH
может иногда работать, потому что могут быть разные версии msys-1.0.dll
в разных версиях Git или других MSYS-приложений, которые, возможно, используют другой адрес, разный размер этой кучи и т. Д.
- Перебазировка
msys-1.0.dll
может быть пустой тратой времени, потому что 1) будучи DLL, она уже имеет информацию о перемещении и 2) «в любой версии ОС Windows нет гарантии, что (...) DLL всегда будет загружаться в одном и том же адресном пространстве» во всяком случае ( источник ). Единственный способ, которым это может помочь, - это если msys-1.0.dll
сам загружается по конфликтующему адресу, который он затем пытается использовать. По-видимому, иногда так и происходит, поскольку именно так Git для Windows делают автоматически на 32-битных системах .
- Учитывая вышеприведенные выводы, я изначально установил
msys-1.0.dll
двоичный код для двоичного кода, чтобы использовать другое значение, _cygheap_start
и это немедленно решило проблему.