Question

FastMM reports a memory leak (UnicodeString) for the following code snippet that uses a record thread variable with a string:

program Project10;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  FastMM4,
  System.SysUtils;

type
  TContext = record
    Value : String;
  end;

threadvar
  Context : TContext;

begin
Context.Value := 'asdfsdfasfdsa';
end.

Is this a real memory leak or is the cleanup of thread variables just happening after FastMM checks for memory leaks?

Even more important: how can I suppress these "memory leaks" being reported as they clutter up any other memory leaks that might be found?

Was it helpful?

Solution

That's a real leak. Thread local variables are not finalized when they go out of scope. Because your record contains a field that is managed, the string field, the heap allocated memory associated with that string is leaked if the record is not finalized.

The documentation calls this out explicitly:

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.

If you want to plug the leak, you'll need to finalize the variable as the scope ends. That is, as the thread is terminating.

Finalize(Context);

Note that you must execute this code from the thread which owns the variable since, obviously, only that thread has access to it.

If you want to suppress reporting of these leaks then call RegisterExpectedMemoryLeak.

If you cannot execute code when threads terminate then it may be better to avoid heap allocation and use a fixed length character array. Quite possibly that you meet your needs.

It would seem odd that you claim not to be able to execute code when the threads terminate. If you cannot do that, how are you able to execute any code in the context of these threads. In other words, in order for there to be a leak, you must have executed your code in these threads.

OTHER TIPS

Create global array of TContext, and then store index of the element, that belongs to your thread, in a threadvar.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top