开发者

delphi string leak

I'm working with Delphi XE, and writing an application that is using RemObjects SDK to communicate (in case that may be relevant). I have FastMM debug on, and sometimes (not always) when I close it gives a warning about a single "Unexpected Memory Leak". "An unexpected memory leak开发者_StackOverflow has occurred. The unexpected small block leaks are: 117-124 bytes: UnicodeString x 1". Very occasionally, I get x2 reported.

Now, my understanding is that Strings are reference counted, and since there is no other object involved to cause the leak, what might be the situation that could cause this to happen? In this StackOverflow question people cannot find a way to make a leak.

If there is no obvious way, then I will download the latest FastMM source (it appears not to be included with the XE source).

[Edit once resolved] The solution to finding this was to install FastMM source, and enable the FullDebugMode to get the stack trace.


When using typed constants and depending on finalization order, it used to be possible for FastMM to report a leak when there really isn't.

FastMM: Leaked memory reported where I believe it shouldn't.

In short, when the FinalizedFirst unit get's finalized, the SString constant get's freed. After finalization of the unit is done, the finalization of FinalizedLast get's called. In it is finalization, it call's the method LeakMemory of the FinalizedFirst method. The SString variable gets initialized again and doesn't get freed as the finalization of FinalizedFirst has already run.

FinalizedLast Unit

unit FinalizedLast;    

interface

uses FinalizedFirst;

implementation

initialization LeakMemory;
finalization LeakMemory;
end.

FinalizedFirst Unit

unit FinalizedFirst;

interface

procedure LeakMemory;

implementation

uses FinalizedLast;

procedure LeakMemory;
const
  SString: string = '';
begin
  //***** SString will get initialized once or twice depending on the
  // finalization order of units. If it get's initialized twice,
  // a memory leak is reported.
  if SString = '' then
  SString := 'FooBar';
end;
end.

Project LeakMemory

program LeakMemory;
uses
FastMM4 in 'FastMM4.pas',
Forms,
FinalizedFirst in 'FinalizedFirst.pas',
FinalizedLast in 'FinalizedLast.pas';

{$R *.RES}
begin

Application.Initialize;
Application.Run;

end.


You can leak strings by freeing records on the heap using FreeMem instead of Dispose or if you overwrite a record using System.Move or FillChar. In the first case the finalization code isn't run and in the second if the string field was filled with a nil it will think it's already cleared it.

If you want to find the location for the leak download FastMM and turn on FullDebugMode. It will include a stack trace of where the leak occurred.


The only way that comes to mind where you can leak a string without deliberately breaking it (like manually incrementing the ref count or doing some messy pointer operation) is by using threadvar.

Like the help file states,

Dynamic variables that are ordinarily managed by the compiler (long strings, wide strings, dynamic arrays, variants, and interfaces) can be declared with threadvar, but the compiler does not automatically free the heap-allocated memory created by each thread of execution. If you use these data types in thread variables, it is your responsibility to dispose of their memory from within the thread, before the thread terminates.

Beside that, there's nothing that comes to mind that wasn't already stated.

[Edit by questioner] This was indeed the issue, and the specific code was as follows:

threadvar
    g_szAuthentication : String;


procedure TMyBase.SetAuthentication(szUserName, szPassword: String);
begin
    g_szAuthentication := '?name=' + szUserName + '&pass=' + szPassword;
end;


I usually see string leaks when they are contained inside other objects that have not been destroyed properly. For example an object that has not been freed. However, you would expect to see that object reported too.

The way to resolve this is to download and use the full version of FastMM and configure it to report stack traces when it detects leaks. When you do that you will get a full stack trace of the code that allocated the leaked object and at that point it is usually clear what the problem is.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜