English 中文(简体)
泄漏AnsiStrings的德尔斐应用程序
原标题:Delphi application leaking AnsiStrings

根据Fast MM4, 我目前正在做的戴尔菲计划 正在泄漏许多字符串。 AnsiStrings to certainly:

""https://i.sstatic.net/287c9.png" alt="此处输入图像描述"/"

该应用程序("http://sourceforge.net/projects/orwelldevcpp/" rel="noreferrer" >http://sourceforge.net/projects/orwelldevcpp/ )用来泄漏更多其他类型的数据,但FastMM4可以报告创建实例的地点,所以我设法解决了这个问题。奇怪的是,FastMMM4没有报告这些泄漏的地点。

“强势”编辑:看来它毕竟确实如此,看到解决问题的答案。不管怎样,问题仍然存在:我到底怎么泄露这些东西?

所以,嗯,很不幸,我不知道该找什么。我的意思是,如果这些事情超出范围,就应该自动释放它们的权利(即使它们在堆积物上)?

我设法通过随机评论 追踪了几处漏水 并观察了计数结果

// simply passing it a constant creates a leak...
MainForm.UpdateSplash( Creating extra dialogs... );

procedure TMainForm.UpdateSplash(const text : AnsiString);
begin
  if not devData.NoSplashScreen then // even if this branch is NOT taken
    SplashForm.Statusbar.SimpleText :=  blablabla  + text;
end;

// And even if the function call itself is placed within a NOT taken branch!

以下是另一个泄漏的例子:

// Passing this constants produces leaks...
procedure TCodeInsList.AddItemByValues(const a, b, c: AnsiString;...);
var
  assembleditem : PCodeIns;
begin
   new(assembleditem);
   assembleditem^.Caption:=a;
   assembleditem^.Line:=b;
   assembleditem^.Desc:=c;
   ...
   fList.Add(assembleditem);
end;

// ... even when calling this on WM_DESTROY!
destructor TCodeInsList.Destroy;
var
  I: integer;
begin
  for I := 0 to fList.Count - 1 do
    Dispose(fList[I]);
  fList.Free;
  inherited Destroy;
end;

// produces leaks!?

这里有很多串漏漏密问题, 但没有任何问题能真正澄清“ 坚固” 的图案。 Google 也没有提供 。

<强力 > 编辑 : 所以, 我必须寻找通过常数。 但是为什么?

<% 1⁄4 ̄ ̧漯B/% 1⁄4 ̄ ̧漯B

最佳回答

您不需要明确分配字符串。 除了处理参考数字外, 对象或记录的字符串字段也可能泄漏。 例如,

type
  PRecord = ^TRecord;
  TRecord = record
    S: string;
  end;

procedure TForm1.Button4Click(Sender: TObject);
var
  r: PRecord;
begin
  GetMem(r, SizeOf(r^));
  Initialize(r^);
  r.S :=    ;
  FreeMem(r);

在上述例子中,由于记录本身的内存已解开,快MM将只报告泄漏的字符串。


在任何情况下, FastMM 在对话框中未显示堆放踪迹并不意味着它缺少此信息 。 请确认在可执行文件目录中有 < code> Full DebugMode 、 < code> LogMemory Leak DetailToFile LogErrorsToFile 的定义是 FastM4Opps. inc 。 然后查找 [可执行名]_MemoryManager_ventLog. txt文件 。

对于上述例子,FastMM 生成以下文件:

--------------------------------2012/5/27 4:34:46--------------------------------
A memory block has been leaked. The size is: 12

Stack trace of when this block was allocated (return addresses):
40305E 
404B5D 
404AF0 
45C47B 
43D726 
42B0C3 
42B1C1 
43D21E 
76C4702C [GetWindowLongW]
77AE3CC3 [Unknown function at RtlImageNtHeader]

The block is currently used for an object of class: Unknown

The allocation number is: 484

Current memory dump of 256 bytes starting at pointer address 7EF8DEF8:
01 00 00 ...
...

现在您可以运行该应用程序, pause 它,然后搜索地址。对于上述日志和测试应用程序,地址确定为:

Stack trace of when this block was allocated (return addresses):
40305E    -> _GetMem
404B5D    -> _NewAnsiString
404AF0    -> _LStrAsg
45C47B    -> TForm1.Button4Click (on FreeMem line)
43D726    -> TControl.Click
... 


edit: Instead of manually looking up addresses, generate a detailed map file through linker options and FastMM will do it (thanks to Mason s comment).


您对问题的编辑反映了与上述示例中相似的泄漏。 如果 fList 是常规 < code> TList , 它只是持有指针, 并且不知道这些指针指针指向什么。 因此, 当您处置指针时, 只释放了为指针本身分配的内存, 而不是记录字段。 因此, 泄漏与函数传递的常数无关, 但和下面的模式一样 :

var
  assembleditem: PCodeIns;
  p: Pointer;
begin
  new(assembleditem);
  assembleditem^.Caption:= a ;
  ..    
  p := assembleditem;
  Dispose(p);

要处置记录,代码应按类型键入指针:

Dispose(PCodeIns(p));

所以,你的TCodinsList。 破坏应该是:

destructor TCodeInsList.Destroy;
var
  I: integer;
begin
  for I := 0 to fList.Count - 1 do
    Dispose(PCodeIns(fList[I]));
  fList.Free;
  inherited Destroy;
end;


在结尾处, 您所要查找的图案似乎正在寻找代码意在释放含有字符串字段的记录( 不太可能的物件) 的地方。 寻找 < code> dispose , 可能性略小于 FreeMem , 更少的可能性 FreeInstance 来释放 FastMM 显示作为分配内存泄漏的对象/ 记录。

问题回答

你说的对 弦应该自动清理 我见过一些方法来搞砸它

第一种是,如果您正直接用字符串数据结构做一些可以断开引用计数的事情。这是最有可能的,因为您正在泄漏的字符串数量。

另一个是叫“停”并在堆栈上留下字符串参考。但您不会在堆栈上留下40,000个字符串参考, 所以我会寻找通过字符串的代码, 然后用其参考计数小提琴。

使用简短的单词, Delphi 内嵌字符串类型会被计为参考值。 内存分配和处置方法不注意更新引用计数, 以便编译者不知道您记录中的字符串可以被实际解开 。

它不鼓励用参考字符串类型来定义记录。 我以前也有同样的混乱。 如果您查看德尔斐图书馆的来源, 你会发现许多记录有PChar而不是字符串。

泄漏字符串最常见的方法是拥有包含字符串和该记录指针的记录。 如果您只是对该指针进行分解, 编译者将只释放指针, 而不是子集记录中的所有内容。 总是要确保您的处置代码告诉编译者你正在处理的内容 。

例如,假设在TTreeView中,我在节点Data中将 PMyRecord = 插入到节点中。如果,在结尾处,您环绕所有节点,简单做 Dispose(Node.Data) ,那么我的记录中的任何字符串都不会被正确处理 。

但如果您通过向编译者明确告知指针的下层类型来处置指针, 调用 dispose( PmyRecord( Node.Data)) < /code>, 那么就不会有内存泄漏 。

我发现一个字符串(记录中的字段)即使没有内存分配/指针操作也可以泄漏。

这听起来很疯狂,但确实如此,至少在XE3中是这样。

TMyRecord = record
x,
y: integer;
s: ansistring;
end;

function GetMyRec: TMyRecord;
begin
....
end;

....
procedure DoSomething;
var
  rec: TMyRecord;
begin
  ...
  rec := GetMyRec; //First call - everything is OK
  ...
  rec := GetMyRec; //Repeated call > Memory Leak of 
                   //Ansistring !!!!
  //To avoid the leak do the following BEFORE a 
  //repeated call: rec.s := unassigned;
end;




相关问题
Simple JAVA: Password Verifier problem

I have a simple problem that says: A password for xyz corporation is supposed to be 6 characters long and made up of a combination of letters and digits. Write a program fragment to read in a string ...

Case insensitive comparison of strings in shell script

The == operator is used to compare two strings in shell script. However, I want to compare two strings ignoring case, how can it be done? Is there any standard command for this?

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

String initialization with pair of iterators

I m trying to initialize string with iterators and something like this works: ifstream fin("tmp.txt"); istream_iterator<char> in_i(fin), eos; //here eos is 1 over the end string s(in_i, ...

break a string in parts

I have a string "pc1|pc2|pc3|" I want to get each word on different line like: pc1 pc2 pc3 I need to do this in C#... any suggestions??

Quick padding of a string in Delphi

I was trying to speed up a certain routine in an application, and my profiler, AQTime, identified one method in particular as a bottleneck. The method has been with us for years, and is part of a "...