10

.bpl 内にユニットがあり、作成した新しい関数の文字列リストが必要です。各呼び出しが前の呼び出しで見つかったものに基づいて構築できるように、文字列リストをアプリの存続期間中存続させたいと考えています。

したがって、ユニット内でグローバルに宣言され、次のように初期化セクションで初期化します。

var
  ProductLookup : TStrings;  
...

function foo : boolean;
begin
  result := (ProductLookup.IndexOfName('bar') >=0); //blow up here. It's nil. Why?
end;
....

initialization
  ProductLookup := TStringList.Create;  // This should get run, but doesn't.

finalization
  FreeAndNil(ProductLookup);

end.

単体テストを行ったところ、すべて問題ありませんでした。しかし、メイン アプリから実行すると、文字列リストが nil だったため、アクセス違反が発生しました。だから今、私は foo 関数で nil をチェックし、必要に応じて作成することに頼っています。しかし、初期化がうまくいかない理由がわかりません。私は初期化にデバッグメッセージを入れました。これがBPLとして読み込まれると実行されませんが、dUnit exeに直接コンパイルすると実行されます。何か案は?Delphi2005.

4

4 に答える 4

27

ダリアンは私が以前にこれに答えたことがあることを私に思い出させます:

オペレーティングシステムが関連するEXEのロードの一部としてBPLをロードする場合、すべての初期化セクションが呼び出されるわけではありません。代わりに、プログラム内の他の何かによって明示的に使用されているユニットのセクションのみが呼び出されます。

初期化セクションのコードがクラスを登録し、そのクラスを間接的に参照するだけの場合、たとえばリストで名前で検索すると、ユニットの初期化セクションが呼び出されない場合があります。そのユニットをプログラムの「uses」句に追加すると、その問題が解決するはずです。

この問題を回避するInitializePackageには、SysUtilsユニットで関数を呼び出して、パッケージのユニットを自分で初期化できます。モジュールハンドルが必要です。これは、GetModuleHandleAPI関数を呼び出すことで取得できます。この関数は、まだ初期化されていないユニットの初期化セクションのみを呼び出します。とにかく、それは私の観察です。

を呼び出す場合はInitializePackage、も呼び出す必要がありますFinalizePackage。パッケージがアンロードされると、自動的に初期化されたすべてのユニットに対してファイナライズセクションが呼び出されます。

OSがパッケージを自動的にロードしないLoadPackage場合は、関数を使用してパッケージをロードしています。パッケージのすべてのユニットが初期化されるため、自分で呼び出す必要はありませんInitializePackage。同様に、UnloadPackageあなたのためにすべてを完成させます。

于 2011-01-06T19:35:40.113 に答える
3

Quality Central で見つかった参照は 1 つだけですが、他にもある可能性があります。LoadPackage 参照の回避策が含まれています。

http://qc.embarcadero.com/wc/qcmain.aspx?d=61968

于 2011-01-06T19:25:13.327 に答える
1

特定の状況下では、BPL 内のすべてのユニットが必ずしも初期化されるわけではありません。推測するなら、この BPL はロード時にプログラムにリンクされ、後で動的にロードされるわけではないと思いますか? 使用しているユニットの名前を、DPRのプログラムの使用リストに入れてみてください。それはそれを修正する必要があります。

于 2011-01-06T19:18:59.163 に答える
-1

bpl をどのようにロードしていますか? ロードを Delphi に任せていますか、それとも手動で bpl をロードしていますか? bpl を手動でロードしている場合、「ストレート」dll としてロードしていますか、それとも LoadPackage を使用して Delphi パッケージとしてロードしていますか? 初期化セクションをvclで実行するには、vclにロードさせる(処理が必要)か、LoadPackageを使用する必要があると思います...

于 2011-01-06T19:17:46.820 に答える