Jump to content
mikak

DunitX / delphi-leakcheck and Rtti

Recommended Posts

Hi,

I'm testing classes that use RTTI and I get some strange leaks. 

My isolated test case is 
 

  [ TestFixture ]
  tSomeTEst = class (TObject)
  private
    a: integer;
    b: string;
    c: double;
  published
    [ test]
    procedure sometest;
  end;
/// ... and the test itself ..

procedure tSomeTEst.sometest;
var
  ctx: TRttiContext;
  ti: TRttiType;
  f: TRttiField;
begin
  ctx := TRttiContext.Create;
  ti := ctx.GetType( typeinfo(Tsometest) );
  for f in ti.GetFields do
     codesite.send(f.Name);
  ctx.free;
end;

When I run my test I get 

  testkassaapi.tSomeTEst.sometest
  Message: 432 bytes were leaked in the test method
Total allocation count: 26532 (1906454 B)
Leak detected 06320CB0 size 76 B for class: TStringList
Leak detected 06519080 size 18 B
  B0 04 02 00 01 00 00 00 02 00 00 00 0D 00 0A 00 00 00 | ??????????????????
Leak detected 065192F0 size 40 B
  01 00 00 00 04 00 00 00 6C 95 51 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ????????l?Q??????????????
???????
  00 00 00 00 00 00 00 00 | ????????
Leak detected 06519560 size 16 B for UnicodeString {RefCount: 1} = a
Leak detected 064A57E0 size 28 B for class: TRttiInstanceFieldEx
Leak detected 064A5A50 size 28 B for class: TRttiInstanceFieldEx
Leak detected 064A5CC0 size 28 B for class: TRttiInstanceFieldEx
Leak detected 064A5F30 size 32 B for UnicodeString {RefCount: 1} = 3676=3676
Leak detected 064A61A0 size 40 B
  01 00 00 00 04 00 00 00 3C 5F 4A 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ????????<_J??????????????
???????
  00 00 00 00 00 00 00 00 | ????????
Leak detected 06320F50 size 86 B for UnicodeString {RefCount: 2} = 2EC5265F-E40C-42B0-B71D-D8C0F8E30803
Leak detected 064A6680 size 40 B
  01 00 00 00 04 00 00 0

If I just use standard ReportmemoryleakOnShutdown, it reports no leaks.

what's going on here? 

I use Delphi 10.3.1. and latest leak-check from https://bitbucket.org/shadow_cs/delphi-leakcheck/src/master/

Share this post


Link to post

That is because internally all RTTI through an TRttiContext is handled by a singleton instance and DUnitX itself is already using some TRttiContext. So the internal singleton already exists and your usage causes it to just create more objects that are then owned by that singleton instance which outlives the unit test because DUnitX keeps it alive.

 

This general issue of cached objects created during unit tests that keep existing after the test ran and thus are considered leaks is known and LeakCheck has mechanisms for that.

 

Add the following line into the dpr (needs LeakCheck and LeakCheck.Utils in the uses)

TLeakCheck.InstanceIgnoredProc := IgnoreRttiObjects;

For more details please see the Ignoring section in the LeakCheck readme

 

In practice there are many more places in RTL and possibly custom code that use lazy creation/caching mechanism and are subject to such a leak detection approach (see InitializeLeakCheck in Spring.TestRunner.pas for some example of such madness if you are curious)

Edited by Stefan Glienke
  • Like 1
  • Thanks 1

Share this post


Link to post

Thanks for reply. I'm quite ashamed of how badly I concentrated to read readme ... there it was, Right before my eyes. 

But opening Spring.TestRunners.pas was quite eye opener! Thanks. Got rid of some unidac singleton and some LazyLoadAttributes.MakeClosure* leaks. 

 

thanks again... 

 

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×