delphi调用pchar引起的delphi dll内存泄漏

时间:2015-12-27 16:07:47

标签: delphi memory-leaks delphi-xe7 pchar

所以我们来看看dll。

如果要将字符串传递给dll调用,则必须将过程输入PChar。否则,你会得到数据。

所以我们说我们的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中我们有一个Form,其中包含FireDacConnection,但其中的任何组件或对象都可以完成工作。

问题是这个PChar被释放两次并导致内存泄漏。我无法找到通过PChar的方法,而不会导致内存泄漏。

你可以使用fastmm,我使用eurukalog,写入

  

| + Leak#2:Type = UnicodeString:Ref count - 1,Content:" \ r \ n&#34 ;;总   大小= 18; Count = 1 |

为什么Unicode字符串的Ref计数为-1?怎么预防呢?如何正确传递Unicode字符串?

我尝试了什么: 把它传递给const。 复制它(如例子和strpcopy和strcopy) 使用局部变量来保存PChar的副本。

编辑: 添加调用代码:

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

添加泄漏日志转储

  
    

| + Leak#2:Type = UnicodeString:Ref count - 1,Content:" \ r \ n&#34 ;;总大小= 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 | Click | 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 | |

  
     

抱歉不清楚,我不知道如何在stackoverflow编辑器中保留标签。

1 个答案:

答案 0 :(得分:1)

Copy(pfff,1,100)很奇怪。您可以直接使用pfff并让编译器自动将指针转换为空终止字符数组到字符串。

FireDacConnection.ConnectionName := pfff;

在致电Show之前,这样做肯定是有道理的。你显示一个无模式的表单,然后设置连接名称,然后释放表单,这似乎很奇怪。实际上,甚至在DLL中显示一个表单看起来很奇怪。

那就是说,这不是你问题的原因。代码泄漏的唯一解释是调用约定不匹配,或者调用站点出错。传递PChar,并像你一样复制副本,不会泄漏。

实现中的调用约定似乎是register。 DLL中的声明应该是:

procedure LookPchar(pfff:Pchar); stdcall;

或者您没有在DLL代码中显示stdcall

您可能在通话网站上犯了错误。也许泄漏就在那里。我们看不到那段代码。

查看各种编辑内容,FastMM报告的问题是代码中没有任何代码产生的泄漏。在解决问题之前,您需要隔离问题。那是你的下一步。

使用PChar可以输入。在另一个方向,从被叫者到来电者,有很多选择,但你没有在这里问过这个问题。关于这个话题有很多问题。