技術的な詳細
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 sourceで確認できます。
アドレス空間のその部分が空いていないのはなぜですか?
多くの理由が考えられます。私の場合、競合するアドレスにロードされた他のモジュールがいくつかありました。
最後のアドレスは約 0x68570000 + 5 MB = 0x68C50000 になりますが、これらの WOW64 関連の DLL が 0x68810000 から上にロードされ、割り当てがブロックされます。
共有 DLL がある場合、Windows は通常、すべてのプロセスで同じ仮想アドレスに DLL をロードして、再配置処理を節約しようとします。今回、これらのシステム コンポーネントが何らかの理由で競合するアドレスにロードされたのは、運が悪いだけです。
Git に Cygwin があるのはなぜですか?
Git は、いくつかの低レベルのコマンドと多くの便利なユーティリティで構成されるリッチ スイートであり、ほとんどが Unix ライクなシステムで開発されているためです。大規模な書き換えを行わずにビルドして実行できるようにするには、少なくとも部分的に Unix に似た環境が必要です。
それを達成するために、人々は MinGW と MSYS を発明しました。これは、Unix のような方法で Windows 上でプログラムを開発するための最小限のビルド ツール セットです。MSYS には共有ライブラリ this も含まれており、msys-1.0.dll
実行時の 2 つのプラットフォーム間の互換性の問題を解決するのに役立ちます。そして、その多くの部分は Cygwin から取られたものです。なぜなら、誰かが既に同じ問題を解決しなければならなかったからです。
したがって、Cygwin ではなく、ここで奇妙な動作をしているのは MinGW のランタイム DLL です。
Cygwin では、このコードは実際には MSYS 1.0 の内容から大幅に変更されています。そのファイルの最後のコミット メッセージには、2001 年からの「Import Cygwin 1.3.4」と書かれています。
現在の CygwinとMSYS の新しいバージョンであるMSYS2 の両方には、既に別のロジックが実装されており、より堅牢であることが期待されます。古い壊れた MSYS システムを使用してまだビルドされているのは、Git for Windows の古いバージョンのみです。
クリーン ソリューション:
- Git for Windows 2をインストールします。適切にメンテナンスされた新しいMSYS2で構築されており、多くの新機能、多数のバグ修正、セキュリティの改善なども含まれています。可能であれば、64 ビット版を使用することもお勧めします。ただし、リベースの回避策は 32 ビット システムのバックグラウンドで自動的に実行されるため、そこで問題が発生する可能性も低くなります。
- コンピューターを再起動してアドレス空間をきれいにする (これらのモジュールを別のランダムなアドレスにロードする) だけでうまくいくかもしれませんが、実際には Git for Windows 2 にアップグレードしてセキュリティ修正を取得するだけです。
ハッキーなソリューション:
- 異なるバージョンの Git または他の MSYS ベースのアプリケーションに異なるバージョンがあり、おそらく異なるアドレス、異なるサイズのこのヒープなどを使用する
PATH
可能性があるため、変更が機能する場合があります。msys-1.0.dll
msys-1.0.dll
1) DLL であるため、既に再配置情報があり、2) 「Windows OS のどのバージョンでも、(...) DLL が常に同じアドレス空間に読み込まれるという保証はない」ため、リベースは時間の無駄になる可能性があります。とにかく(ソース)。これが役立つ唯一の方法は、msys-1.0.dll
それ自体が使用しようとしている競合するアドレスに読み込まれる場合です。これは、Git for Windows の担当者が32 ビット システムで自動的に行っていることであるため、このような場合もあるようです。
msys-1.0.dll
上記の調査結果を考慮して、私はもともとバイナリに別の値を使用するようにバイナリ パッチを適用し_cygheap_start
、問題をすぐに解決しました。