公開されたインターフェイス プロパティを介して相互にリンクする一連のコンポーネントを作成しました。これらはデザイン パッケージに登録され、インストールされます。
公開されたインターフェイス プロパティを使用することは、Delphi ではあまり一般的ではないため、当然のことながら、うまく機能していないように見えます。
コンポーネントが同じフォームに存在する場合は正常に機能しますが、異なるフォーム上のコンポーネント間のインターフェイス プロパティ リンクは問題を引き起こします。
別のフォーム上のコンポーネントへのオブジェクト リンクとは異なり、インターフェイス リンクは IDE によって認識されないようです。IDE で 2 つのフォームを開いていて、それらのコンポーネント間にリンクがある場合、フォーム ビューをテキスト (Alt+F12) として切り替えようとすると、IDE は次のように正しく不平を言います:
Module 'UnitXXX.pas' has open descendents or linked modules. Cannot close.
ただし、プロパティがインターフェイスの場合、これは発生せず、代わりにリンクが切断されます (これは、通知メカニズムを使用して参照をクリアする場合の最良のシナリオです。そうしないと、無効なポインターが残ります)。
同じバグの結果として考えられるもう 1 つの問題は、IDE でプロジェクトを開くときに、フォームが再度開かれる順序が定義されていないため、IDE がコンポーネントへのインターフェイス リンクを持つコンポーネントを含むフォームを開こうとする可能性があることです。別のフォームですが、その別のフォームはまだ再作成されていません。したがって、これは事実上、AV または切断されたリンクのいずれかになります。
Datasets
私が使用していた90年代に戻って、Datasources
フォーム間のリンクが消えるという同様の問題を覚えているので、これはやや似ています.
一時的な回避策として、公開されたプロパティを複製して追加し、インターフェイス プロパティごとに として宣言されている別のプロパティを追加しましたTComponent
。これにより、Delphi はフォーム間にリンクがあることを認識できますが、控えめに言っても醜い回避策です。
この問題を解決するために何かできることがあるのだろうか?これは IDE のバグであり、おそらく直接修正することはできませんが、おそらく何かをオーバーライドするか、ストリーミング メカニズムにフックして、このバグをより効果的に回避することができます。
ストリーミング メカニズムについてこれほど深く掘り下げたことはありませんが、Fixup メカニズムがこれに対処することになっているのではないかと思います。があるcsFixups
TComponentState
ので、回避策が可能であることを願っています。
編集: D2007を使用しています。
アップデート:
http://www.filedropper.com/fixupbugproject2にアップロードされた新しい更新された再現可能な例
property ComponentReference: TComponent
インターフェイスとコンポーネントのストリーミングを簡単に比較およびトレースできるように追加されました。
問題をアセンブラー レベルにまで絞り込みましたが、これは私の深みからは少し外れています。
ユニット内のプロシージャGlobalFixupReferences
では、次のclasses
ように呼び出します。
(GetOrdProp(FInstance, FPropInfo) <> 0)
最終的に実行されます:
function TInterfacedComponent.GetInterfaceReference: IInterface;
begin
// uncomment the code bellow to avoid exception
{ if (csLoading in ComponentState) and (FInterfaceReference = nil) then
// leave result unassigned to avoid exception
else
}
result := FInterfaceReference; // <----- Exception happens here
end;
コメントからわかるように、例外を回避するために私が見つけた唯一の方法は、結果を割り当てないままにすることですが、リンクが切断GlobalFixupReferences
されたために上記の比較が失敗するため、機能が壊れます。GetOrdProp <> 0
例外のより正確な場所をより深くトレースします
procedure _IntfCopy(var Dest: IInterface; const Source: IInterface);
system
単位で
この行は特に発生しますread of address 0x80000000
{ Now we're into the less common cases. }
@@NilSource:
MOV ECX, [EAX] // get current value
それで、なぜMOV
失敗し、何が問題なのかECX
、EAX
私にはわかりません。