0

I suspect that a double-free error leads to an access violation (later in the same program).

The given class contains a Generic TDictionary and assigns a ChangeNotification handler after creating it using FMyDict.OnValueNotify := ChangeNotification;

procedure TMyClass.ChangeNotification(Sender: TObject; const Item: TMyValueType; Action: TCollectionNotification);
begin
   if Action = cnRemoved then begin
     Item.Free;
   end;
end;

If I uncomment the Item.Free, the AV does no longer occur.

But because the AV appears sporiadically (once in several hundreds of loop iterations in the program) I can't exactly prove that there is a double free situation.

My first idea is to set some "marker" in the object before freeing it. On the second free I could see that this marker is set.

Or is there a different "best practice" for detection of a double-free?

mjn
  • 36,362
  • 28
  • 176
  • 378
  • 1
    When the object is freed, you no longer own the memory previously occupied by the object. This memory might even be used by some other part of your application. Hence you cannot assume anything about this location in memory. In particular, you cannot leave a marker here. The only thing you can do is to make sure you don't call `Free` on a dangling pointer. – Andreas Rejbrand Jun 17 '20 at 09:45
  • 1
    Override the dtor of the objects in question and write a log. – Stefan Glienke Jun 17 '20 at 09:47
  • @StefanGlienke I like this idea :) maybe I can keep a list in memory (and check it for "duplicates") – mjn Jun 17 '20 at 09:59
  • 2
    FastMM4 full debug will detect double free. – David Heffernan Jun 17 '20 at 10:20
  • @DavidHeffernan good catch, I tried FastMM4 in full debug mode and did not get a double free error. I will test an intentional double free to verify I don't have a configuration problem. – mjn Jun 17 '20 at 11:13
  • 1
    Why not use a `TObjectDictionary`? This is exactly what it's for. – J... Jun 17 '20 at 13:34
  • @J... right, but actually FastMM4 did not find any double-frees so I need to find the cause of the AV somewhere else first (switching to TObjectDictionary is something for later) – mjn Jun 17 '20 at 13:46
  • Do you have a stack trace for the AV? What is the read of address for the AV? Maybe `Item` is nil? – J... Jun 17 '20 at 13:49
  • The AV happens in a different part of the code (see https://stackoverflow.com/questions/62306617/) – mjn Jun 17 '20 at 14:00
  • 1
    Aren’t you accidentally adding the same object twice using different keys? Hence, when removing one of the two will free the object and leave a invalid pointer in the other. – R. Hoek Jun 19 '20 at 21:25

0 Answers0