Chi tiết kỹ thuật
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
Bản thân triệu chứng này không liên quan gì đến các cơ sở hình ảnh của các tệp thực thi, các phần bộ nhớ dùng chung của Cygwin bị hỏng, các phiên bản mâu thuẫn của DLL, v.v.
Đó là mã Cygwin không cấp phát một khối bộ nhớ lớn ~ 5 MB cho heap của nó tại địa chỉ cố định 0x68570000 này, trong khi chỉ có một lỗ lớn ~ 2,5 MB có sẵn ở đó. Các mã có liên quan có thể được nhìn thấy trong nguồn msysgit .
Tại sao một phần của không gian địa chỉ không miễn phí?
Có thể có nhiều lý do. Trong trường hợp của tôi, đó là một số mô-đun khác được tải tại một địa chỉ xung đột:
Địa chỉ cuối cùng sẽ vào khoảng 0x68570000 + 5 MB = 0x68C50000, nhưng có những DLL liên quan đến WOW64 được tải từ 0x68810000 trở lên, chặn phân bổ.
Bất cứ khi nào có một số DLL được chia sẻ, Windows nói chung sẽ cố gắng tải nó tại cùng một địa chỉ ảo trong tất cả các quy trình để lưu một số xử lý di dời. Đây chỉ là một vấn đề xui xẻo khi các thành phần hệ thống này được tải bằng cách nào đó tại một địa chỉ xung đột lần này .
Tại sao có Cygwin trong Git của bạn?
Bởi vì Git là một bộ phần mềm phong phú bao gồm một số lệnh cấp thấp và rất nhiều tiện ích hữu ích và chủ yếu được phát triển trên các hệ thống giống như Unix. Để có thể xây dựng nó và chạy nó mà không cần viết lại lớn, nó cần ít nhất một môi trường giống như một phần Unix.
Để thực hiện điều đó, mọi người đã phát minh ra MinGW và MSYS - một bộ công cụ xây dựng tối thiểu để phát triển các chương trình trên Windows theo kiểu Unix. MSYS cũng chứa một thư viện chia sẻ, cái nàymsys-1.0.dll
giúp giải quyết một số vấn đề tương thích giữa hai nền tảng trong thời gian chạy. Và nhiều phần trong số đó đã được lấy từ Cygwin, bởi vì ai đó đã phải giải quyết những vấn đề tương tự ở đó.
Vậy đó không phải Cygwin, đó là DLL thời gian chạy của MinGW, những thứ hành xử kỳ lạ ở đây.
Trong Cygwin, mã này thực sự đã thay đổi rất nhiều kể từ những gì trong MSYS 1.0 - thông báo cam kết cuối cùng cho tệp đó "Nhập Cygwin 1.3.4", từ năm 2001!
Cả Cygwin hiện tại và phiên bản mới của MSYS - MSYS2 - đã có logic khác nhau, hy vọng sẽ mạnh mẽ hơn. Đây chỉ là phiên bản cũ của Git cho Windows vẫn được xây dựng bằng hệ thống MSYS cũ bị hỏng.
Giải pháp sạch:
- Cài đặt Git cho Windows 2 - nó được xây dựng với MSYS2 mới, được bảo trì đúng cách và cũng có nhiều tính năng mới, nhiều sửa lỗi, cải tiến bảo mật, v.v. Nếu có thể, cũng nên sử dụng phiên bản 64 bit . Nhưng cách giải quyết rebase được thực hiện tự động phía sau hậu trường cho các hệ thống 32 bit, do đó, khả năng xảy ra sự cố cũng sẽ thấp hơn.
- Chỉ cần khởi động lại máy tính để dọn sạch không gian địa chỉ (tải các mô-đun này ở một địa chỉ ngẫu nhiên khác) có thể hoạt động, nhưng thực sự, chỉ cần nâng cấp lên Git cho Windows 2 để sửa lỗi bảo mật nếu không có gì khác.
Giải pháp mạnh mẽ:
- Việc thay đổi
PATH
đôi khi có thể hoạt động vì có thể có các phiên bản khác nhau msys-1.0.dll
trong các phiên bản khác nhau của Git hoặc các ứng dụng dựa trên MSYS khác, có thể sử dụng địa chỉ khác nhau, kích thước khác nhau của heap này, v.v.
- Việc khởi động lại
msys-1.0.dll
có thể gây lãng phí thời gian, bởi vì 1) là một DLL, nó đã có thông tin di dời và 2) "trong bất kỳ phiên bản Windows OS nào, không có gì đảm bảo rằng (...) DLL sẽ luôn tải ở cùng một không gian địa chỉ" dù sao ( nguồn ). Cách duy nhất điều này có thể giúp là nếu msys-1.0.dll
chính nó tải tại địa chỉ xung đột thì nó sẽ cố gắng sử dụng. Rõ ràng đôi khi đó là trường hợp, vì đây là điều mà các Git cho Windows đang thực hiện tự động trên các hệ thống 32 bit .
- Xem xét những phát hiện ở trên, ban đầu tôi đã vá
msys-1.0.dll
nhị phân để sử dụng một giá trị khác _cygheap_start
và điều đó đã giải quyết vấn đề ngay lập tức.