Working with Interfaces is surprising

Working with Interfaces is surprising

just noticed that the nice compact code
myList.Sort(TMyComparer.Create);
leads to a memory leak while

intfComp: IComparer;
...
intfComp:= TMyComparer.Create;
myList.Sort(intfComp);
does free the interfaced object correctly.

Looks as the "const" of the parameter declaration is the Sort does prevent the compiler adding the add/remove refs. I tested that and SortX (no const parameter) does free properly.

procedure TListX.SortX(AComparer: IComparer);
begin
  Sort(AComparer);
end;

Is that not a complete violation of the concepts that the implementation details should not influence the calling code. Has a developer really to take are on such traps?

Comments

  1. Stefan Glienke go it now, thanks!

    What about the factory method?

    ReplyDelete
  2. Asbjørn Heid You are not missing anything. This is plain bug.

    ReplyDelete
  3. thank you all for your feedback. To summarize

    a) a already known bug/problem/feature since long time

    b) const interface parameters do not inc/dec the ref counters for speed

    c) not easy to be avoided by a compiler enhancement:

    c1) a constructor used directly as interface argument could be "saved" by compiler adding on fly a temp var (the normal case for modern patterns)

    c2) but arguments that point to methods or singletons will still not "add/dec refs" (rare case)

    d) Embarcadero has

    d1) agreed that it's a bug in the implementation of the interface specification as the behavior is "strange/magic" for the normal developer.
    (Barry Kelly)

    d2) the problem has been discussed a lot internally but no decision was taken for not "breaking existing code" (Marco Cantu)

    e) the only clear workaround is as David Heffernan suggests: never create an interfaced object without a local variable.

    ReplyDelete

Post a Comment