3

起動時に多数のライブラリをロードするホスト アプリケーションがあります。Delphi 7 のデフォルト メモリ マネージャから FastMM4 のフル バージョンに切り替えて、メモリ リーク レポートを改善したいと考えています。

ホスト アプリケーションとライブラリの両方の uses セクションに FastMM4 を含める必要がありますか? 共有ランタイム パッケージはどうですか?


いくつかの追加情報:

  • 1 つの exe と 20 以上の dll があります。全員が 1 つのランタイム パッケージを共有しています。
  • 現在、sharemem は使用していません。私が知っていることではありません。ShareMem は、今日簡単に調べた exe または dll の 8 分の 1 には含まれていません。

追加の質問:

  • すべてのプロジェクトで fastmems inc ファイル内で同じオプションを使用できますか、それとも exe と dll で異なる設定が必要ですか?
4

6 に答える 6

8

FastMM4options.incファイル からの抜粋。

私にとっては、すべてのパッケージ、dll、および実行可能ファイルがShareMMでコンパイルされている場合、Delphi7sのデフォルトのメモリマネージャーを置き換えることができるはずです。

{-----------------------メモリマネージャの共有オプション---------------------- -}

{メインアプリケーションと、FastMMでコンパイルされたDLLとの間でメモリマネージャーを共有できるようにします。これにより、FastMMを使用するようにコンパイルされている場合、動的配列と長い文字列をDLL関数に渡すことができます。共有は、メ​​モリマネージャを共有することになっているライブラリが「AttemptToUseSharedMM」オプションセットでコンパイルされている場合にのみ機能します。メインアプリケーションがシングルスレッドでDLLがマルチスレッドの場合、メインアプリケーションのIsMultiThread変数をtrueに設定する必要があります。そうしないと、スレッドの競合が発生したときにクラッシュします。静的にリンクされたDLLファイルはメインアプリケーションの前に初期化されるため、メインアプリケーションは静的にロードされたDLLのメモリマネージャーを共有することになり、その逆ではないことに注意してください。}

{。$defineShareMM}

{DLLによるメモリマネージャの共有を、FastMMでコンパイルされた他のDLL(または静的にロードされたDLLの場合はメインアプリケーション)と許可します。動的にロードされるDLLでは、このオプションを慎重に設定してください。MMを共有しているDLLがアンロードされ、他のDLLがまだMMを共有している場合、アプリケーションがクラッシュするためです。この設定はDLLライブラリにのみ関連し、ShareMMも効果を発揮するように設定する必要があります。共有は、メ​​モリマネージャを共有することになっているライブラリが「AttemptToUseSharedMM」オプションセットでコンパイルされている場合にのみ機能します。DLLが静的にリンクされている場合、DLLはメインアプリケーションの前に初期化され、DLLは実際にそのMMをメインアプリケーションと共有することに注意してください。

{。$defineShareMMIfLibrary}

{これを定義して、ShareMMセットでコンパイルされた同じプロセスでメインアプリケーションまたは他のロードされたDLLのMMを共有しようとします。メモリマネージャを共有する場合、共有者によって引き起こされたメモリリークは自動的に解放されません。静的にリンクされたDLLはメインアプリケーションの前に初期化されることを考慮に入れて、それに応じて共有オプションを設定してください。}

{。$defineAttemptToUseSharedMM}

{これを定義して、Delphi 2006および2007、および古いFastMMバージョンで使用されているメモリマネージャ共有メカニズムの下位互換性を有効にします。}

{$ define EnableBackwardCompatibleMMSharing}

于 2010-06-07T12:34:07.573 に答える
3

あなたが探しているものはSimpleShareMemと呼ばれています。FastMMパッケージに含まれています。アプリとDLLの両方がそれを使用していることと、 uses句の先頭にあるFastMM4を使用していることを確認してください。これにより、別々のヒープを使用するのではなく、すべてが同じヒープを共有するようになります。

もちろん、共有メモリが必要になるのは、アプリとライブラリ(文字列やオブジェクトなど)の間で動的メモリを渡す場合のみです。そうでない場合は、SimpleShareMemは必要ありませんが、パフォーマンスと安定性を向上させるために、メモリマネージャーとしてライブラリをFastMMに切り替えることをお勧めします。

于 2010-06-07T12:34:26.673 に答える
1

「誰もが単一のランタイム パッケージを共有している」ためです。私が使用している方法をお勧めします。FastMM4 を共有ランタイム パッケージに追加するだけです (もちろん、FastMM4 を各ライブラリとホスト アプリケーションの "using" 宣言に入れる必要があります)。この方法には、次のような利点があります。

  • FullDebugMode のオン/オフを切り替える簡単な方法 [もちろん他のオプションも]。プロジェクトの再コンパイルは必要ありません。FastMM は 1 回だけインスタンス化されるため、共有パッケージを再コンパイルするだけで、アプリケーション全体 (dll を含む) の FullDebugMode を切り替えることができます。

  • バージョン管理の問題はありません。FastMM (一度使用すると、アプリ全体とプラグインの重要なコンポーネントになります) を更新すると、ビルド全体 (アプリとプラグイン) を再度出荷する必要はありません。ここでも、共有パッケージを更新するだけで十分です。

  • プラグインをアンロードするときのメモリ マネージャーの問題はありません。最初のプラグイン ライブラリがアンロードされた後に FastMM がアンインストールされるという問題が発生したため、アプリケーションのシャットダウン時に大量のバグが発生しました。

  • 追跡の問題はありません。メモリ リークやその他のメモリの問題が発生した場合、DLL コードでバグが発生した場合でも、有効なコール スタックが提供されます。

上記のようにすべてを機能させるために、FastMM4Options.incで使用している(非標準の)オプションを次に示します。

{$define NeverUninstall} {$define UseRuntimePackages} {.$define ShareMM}

残りは変更されていないと思いますが、何か問題がある場合は、ここに完全なファイルがあります: http://pastebin.4programmers.net/693

于 2010-06-09T11:00:18.700 に答える
0

Ypu には 2 つの選択肢があります。FastMM ディストリビューションにある ShareMem ユニットと BorldMM.dll の代替品を引き続き使用するか、実行可能ファイルと DLL の両方を変更して FastMM メモリ マネージャーを含め、ユニットを最初のものとして配置します。また、FastMM4Options.inc にある $DEFINE のいくつかをニーズに合わせて調整する必要があります。AFAIK ランタイム パッケージは、インストールされたメモリ マネージャーを使用します。

于 2010-06-07T19:08:38.563 に答える
0

知る限り、DLL の境界を越えて共有するための fastmm のバージョンである sharemm があります。

于 2010-06-07T12:21:16.487 に答える
0

アプリケーションがランタイム パッケージでコンパイルされている場合、ランタイム パッケージは常に 1 つのメモリ マネージャーのみを使用するため、追加のアクションは必要ありません。選択したメモリ マネージャーを 1 回だけ指定する必要があります。できればメイン アプリケーション コードで、uses リストの最初のユニットとして指定します。他のすべてのランタイム パッケージは変更を必要としません。メモリ マネージャーが何であれ、正しいメモリ マネージャーが自動的に使用されます。

アプリがランタイム パッケージなしでコンパイルされている場合、すべての dll に独自のメモリ マネージャーがあります。デフォルトでは、それらはすべてデフォルトのメモリ マネージャーを使用します。私が間違っていなければ、これは共有 MM です。つまり、たとえば dll との間で文字列を転送できます。デフォルトの MM を別の共有する MM に置き換える場合は、一緒に作業するすべての dll または exe の uses リストの最初のユニットとして、新しいメモリ マネージャーを含める必要があります。

違いは、ランタイム パッケージでは共有がパッケージ レベルで発生することです。非共有 MM も共有されます。ランタイム パッケージがなければ、すべての DLL が個別の MM を使用し、これらの個別のメモリ マネージャーが協力して共有できるようになるだけです。

私の意見では、アプリが dll と非常に密接にやり取りしない限り (読み取り: dll にフォームとコンポーネントがあります)、メモリ マネージャーを共有することにまったく依存するのではなく、メモリを適切に管理し、誰が作成したかを追跡するのが最善の方法です。オブジェクトをインスタンス化したのと同じライブラリ内のオブジェクトを削除します。それは難しいことではありません。オブジェクトの代わりにインターフェイスを返すか、短い文字列 (固定長) を返すか、文字列を返す代わりに提供されたバッファーにデータをコピーするなどです。呼び出し元によって解放されるものを返さないでください。呼び出し先が解放しなければならないものを受け入れないでください。基本的に安全です。これにより、考えられるすべてのメモリ マネージャーの問題が解決されるだけでなく、任意の言語で dll を記述できるようになります。

于 2010-06-07T13:10:30.660 に答える