所以我们来看看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编辑器中保留标签。
答案 0 :(得分:1)
Copy(pfff,1,100)
很奇怪。您可以直接使用pfff
并让编译器自动将指针转换为空终止字符数组到字符串。
FireDacConnection.ConnectionName := pfff;
在致电Show
之前,这样做肯定是有道理的。你显示一个无模式的表单,然后设置连接名称,然后释放表单,这似乎很奇怪。实际上,甚至在DLL中显示一个表单看起来很奇怪。
那就是说,这不是你问题的原因。代码泄漏的唯一解释是调用约定不匹配,或者调用站点出错。传递PChar
,并像你一样复制副本,不会泄漏。
实现中的调用约定似乎是register
。 DLL中的声明应该是:
procedure LookPchar(pfff:Pchar); stdcall;
或者您没有在DLL代码中显示stdcall
?
您可能在通话网站上犯了错误。也许泄漏就在那里。我们看不到那段代码。
查看各种编辑内容,FastMM报告的问题是代码中没有任何代码产生的泄漏。在解决问题之前,您需要隔离问题。那是你的下一步。
使用PChar
可以输入。在另一个方向,从被叫者到来电者,有很多选择,但你没有在这里问过这个问题。关于这个话题有很多问题。