Windows Server 2003 x64 (現時点で手元にある唯一の 64 ビット環境) で C# のデモをクラッシュさせることはできませんが、コードに欠陥があるため、予期しない動作が見られるのは理にかなっています。
編集:元のコードを使用して Windows Server 2008 R2 x64 でのクラッシュを再現し、修正の有効性を検証しました。
Christian.K が指摘するように、この問題は以前にも指摘されていました。メソッドを呼び出すときは、指定したメモリ ブロックに有効なデータが含まれていない場合にのみ、3 番目のパラメーターMarshal.StructureToPtr
を渡す必要があります。これはドキュメンテーションでかなり明示的に呼び出されているため、元の作成者がどのように間違えたのかはわかりません。true
fDeleteOld
この場合、データは を呼び出して前の行に割り当てられたばかりMarshal.AllocHGlobal
なので、有効なデータが含まれていないため、削除/解放しないでください。変更は簡単です。3 番目のパラメーターtrue
を に変更しますfalse
。残念ながら、サンプル プロジェクトでは相互運用コードが 3 つの異なるクラスに分散しているため、複数の場所を変更する必要があります。あなたが探しているパターンはこれです:
IntPtr ptrStruct = Marshal.AllocHGlobal(Marshal.SizeOf(ti));
Marshal.StructureToPtr(ti, ptrStruct, false /* <-- change this from true to false */);
一般的な観察として、コードはMarshal
、CLR に自動的に処理させるのではなく、多くの相互運用機能を (クラスのメソッドを使用して) 手動で処理しようとします。私は後者の方法を好みます。すべての相互運用を手動で行う方法を完全に理解していますが、システムに管理を任せて、私が犯すミスの数と結果としてのヒープの破損を抑えています。
RhysW氏によると、これまでヒープの破損に遭遇したことはありませんが、.NET コードと Win32 API の間の相互運用を開始すると、非常に一般的になります。.NET Framework はもはやあなたを保護していません。
言いたいことの例として、FMSBalloonTip.SetToolTip
メソッドがメソッドを使用してMarshal.StringToHGlobalAuto
、ツールチップのタイトルを含む文字列をポインターとしてマーシャリングしていることに注意してください。それは確かに機能しますが (作成者は、終了後にポインターを解放するように注意してくれました)、 4 番目のパラメーターとしてオブジェクトSendMessage
を受け入れる関数のオーバーロードを宣言する方がはるかに簡単で、エラーが発生しにくくなります。string
そうすれば、フレームワークは必要なすべての相互運用機能を透過的に処理します。
もちろん、本当の問題は、なぜこのコードが必要なのかということです。最初から利用可能だった組み込みのclassを使用する方がずっとToolTip
簡単です。提供されていない必要な機能について言及しなかったのかToolTip
、単にそれについて知らないだけなのかはわかりませんが、組み込みクラスを利用できるように設計を再検討することを強くお勧めしますMicrosoft のプログラマーにすべての相互運用機能を処理してもらいます。
探しているバルーンパーツの場合は、必ずクラスのIsBalloon
プロパティを設定してください。ToolTip
これは .NET 2.0 まで導入されませんでしたが、サンプル プロジェクトが対象としているのと同じバージョンです。