-3

それでは、dllについて見てみましょう。

文字列を dll 呼び出しに渡したい場合は、プロシージャ入力 PChar を作成する必要があります。それ以外の場合は、データ curroption を取得します。

だから私たちは、私たちのdllが持っていると言います

  procedure LookPchar(pfff:Pchar);stdCall;External 'OutDll.dll';

これはいいです。次に、dll dpr で宣言する内容を見てみましょう。

  procedure LookPchar(pfff:Pchar);
  begin
    with TForm1.Create(nil) do
    try
      show;
      FireDacConnection.ConnectionName := (Copy(pfff,1,100));
    finally
      free;
    end;

  end;
  exports LookPchar;

Dll には FireDacConnection を含む Form がありますが、その中の任意のコンポーネントまたはオブジェクトが機能します。

問題は、この PChar が 2 回解放され、メモリ リークが発生することです。メモリ リークを発生させずに PChar を渡す方法が見つかりません。

あなたはfastmmを使うかもしれません、私はeurukalogを使います。

|+リーク #2: Type=UnicodeString: Ref count - 1, Content: "\r\n"; 合計サイズ=18; カウント=1 |

Unicode 文字列の Ref カウントが -1 になるのはなぜですか? それを防ぐ方法は?Unicode 文字列を正しく渡す方法は?

私が試したこと:constとして渡します。それをコピーします (例と strpcopy および strcopy のように) ローカル変数を使用して PChar のコピーを保持します。

編集:呼び出しコードを追加:

var
  ConnectionName:WideString;
begin
  ConnectionName := 'This Is My String';
  LookPChar(PChar(ConnectionName));
end;

リーク ログ ダンプの追加

|+リーク #2: Type=UnicodeString: Ref count - 1, Content: "\r\n"; 合計サイズ=18; カウント=1 | |---------------------------------------------------------------- -------------------------------------------------- --------------------------------------| |00000002|04 |00000000|01D79D9C|outDll.dll|00009D9C|システム
| |_NewUnicodeString |23897[6] | |00000002|04 |00000000|008A11BC|myapp.exe |004A11BC|発信者
|TForm2 |Button4Click |66[2] | |00000002|04 |00000000|00641C13|myapp.exe |00241C13|Vcl.Controls |TControl |クリック |7348[9] | |00000002|04 |00000000|00646172|myapp.exe |00246172|Vcl.Controls |TWinControl |WndProc |10038[153] | |00000002|04 |00000000|0065B71C|myapp.exe |0025B71C|Vcl.StdCtrls |TButtonControl|WndProc |5163[13] | |00000002|04 |00000000|006462D7|myapp.exe |002462D7|Vcl.Controls | |DoControlMsg |10107[12] | |00000002|04 |00000000|00646172|myapp.exe |00246172|Vcl.Controls |TWinControl |WndProc |10038[153] | |00000002|04 |00000000|0070B240|myapp.exe |0030B240|Vcl.Forms
|TCustomForm |WndProc |4427[206] | |00000002|04 |00000000|006457AC|myapp.exe |002457AC|Vcl.Controls |TWinControl |MainWndProc |9750[3] | |00000002|04 |00000000|004F7614|myapp.exe |000F7614|System.Classes| |StdWndProc
|16600[8] | |00000002|03 |00000000|768162F7|user32.dll
|000162F7|USER32 | | | (gapfnScSendMessage+815 の可能性あり)| | | |00000002|03
|00000000|76816D35|user32.dll |00016D35|USER32 |
| | (可能な GetThreadDesktop+210) | | | |00000002|03
|00000000|76816DE8|user32.dll |00016DE8|USER32 |
| | (GetThreadDesktop+389 の可能性あり) | | | |00000002|03
|00000000|76816E49|user32.dll |00016E49|USER32 |
| | (GetThreadDesktop+486 の可能性あり) | | | |00000002|03
|00000000|77420107|ntdll.dll |00010107|ntdll |
|KiUserCallbackDispatcher | | | |00000002|03
|00000000|768196D0|user32.dll |000196D0|USER32 |
|SendMessageW | | | |00000002|03
|00000000|71AB459B|comctl32.dll |000A459B|comctl32 |
|LoadIconMetric | | | |00000002|03
|00000000|71AB45FE|comctl32.dll |000A45FE|comctl32 |
|LoadIconMetric | | | |00000002|03
|00000000|71AB4488|comctl32.dll |000A4488|comctl32 |
|LoadIconMetric | | | |00000002|03
|00000000|768162F7|user32.dll |000162F7|USER32 |
| | (gapfnScSendMessage+815 の可能性あり)| | | |00000002|03
|00000000|76816D35|user32.dll |00016D35|USER32 |
| | (可能な GetThreadDesktop+210) | | | |00000002|03
|00000000|76820D32|user32.dll |00020D32|USER32 |
| | (可能な GetClientRect+192) | | | |00000002|03
|00000000|76820D56|user32.dll |00020D56|USER32 |
|CallWindowProcW | | | |00000002|04
|00000000|00646282|myapp.exe |00246282|Vcl.Controls |TWinControl
|DefaultHandler |10079[30] | |00000002|04
|00000000|00646172|myapp.exe |00246172|Vcl.Controls |TWinControl
|WndProc |10038[153] | |00000002|04
|00000000|0065B71C|myapp.exe |0025B71C|Vcl.StdCtrls |TButtonControl|WndProc |5163[13] | |00000002|04 |00000000|004F7614|myapp.exe |000F7614|System.Classes| |StdWndProc
|16600[8] | |00000002|03 |00000000|768162F7|user32.dll
|000162F7|USER32 | | | (gapfnScSendMessage+815 の可能性あり)| | | |00000002|03
|00000000|76816D35|user32.dll |00016D35|USER32 |
| | (可能な GetThreadDesktop+210) | | | |00000002|03
|00000000|768177CE|user32.dll |000177CE|USER32 |
| | (可能な CharPrevW+314) | | | |00000002|03
|00000000|76817893|user32.dll |00017893|USER32 |

|DispatchMessageW | | |

申し訳ありませんが、スタックオーバーフローエディターでタブを保持する方法がわかりません。

4

1 に答える 1

1

Copy(pfff,1,100)かなり奇妙です。直接使用pfffして、コンパイラーにポインターからヌル終了文字配列への自動変換を文字列にさせることができます。

FireDacConnection.ConnectionName := pfff;

を呼び出す前にそれを行うことは確かに理にかなっていますShow。フォームをモードレスで表示し、接続名を設定してからフォームを解放するというのは、確かに奇妙に思えます。実際、DLL でフォームを表示することさえ奇妙に見えます。

とはいえ、これはあなたの問題の原因ではありません。コードのリークの唯一の説明は、呼び出し規約の不一致、または呼び出しサイトでのエラーです。を渡してPCharコピーを取っても、リークしません。

実装における呼び出し規約は のようregisterです。DLL 内の宣言は次のようになります。

procedure LookPchar(pfff:Pchar); stdcall;

stdcallまたは、DLL コードで を表示しませんでしたか?

呼び出し場所を間違えた可能性があります。おそらく漏れはそこにあります。そのコードは見えません。

あなたのさまざまな編集を見ると、FastMM は、問題のコードのいずれによっても生成されないリークを報告しています。問題を解決する前に、問題を特定する必要があります。それがあなたの次のステップです。

入力には使用してPCharも問題ありません。他の方向では、呼び出し先から呼び出し元まで、多くのオプションがありますが、ここではそれについて質問していません。そして、そのトピックに関する多くの質問があります。

于 2015-12-27T16:40:33.170 に答える