I've a Delphi client/server project, which uses RemObjects for communication between client and server. In remobject the server and public service functions are defined and interfaces are generated for it. At some points, we need to call other services, from withith another service. In order to do this, we created class methods/functions, pass over the current database connection and remobjects session, an call an implementation of the desired function. For example:
class function TMyService.GetFoo(session: TROSession; conn: Connection): AnsiString;
var
svc: TMyService;
begin
svc := TMyService.Create(nil);
try
IROObjectActivation(svc).OnActivate(session.SessionID, nil);
try
Result := svc.GetFooImpl();
finally
IROObjectActivation(svc).OnDeactivation(session.SessionID);
end;
finally
FreeAndNil(svc);
end;
end;
Some times, looks random, svc seems already to be free'd, before the FreeAndNil call, which causes access violations.
At this point, TMyService, also has a generated interface IMyService, but this only contians the public methods, not the implementations. That's why we use the type instead of the interface to devince the svc
variable.
As far as I know, interfaced objects should be free'd at the end of a method, and not half way. Are there any compiler optimisations which can affect this behaviour?
[edit] By the way, FastMM4 is also compiled in this project, which may have some effect on this. Project compiled with Delphi 10.3
If TMyService
supports interfaces, and you have problems with premature releasing, that means TMyService
class is reference counted class (in other words, it supports interfaces, but reference counting is not disabled).
In such cases you need to store such object instance in interface reference to properly initialize reference counting. Also you should not manually release such object because its memory will be automatically managed, and if you need to access some methods that are not exposed through interface you can do that by typecasting.
However, using methods that are not exposed through interface is potential abuse of the class. Usually, interfaces contain all methods that are meant to be used.
class function TMyService.GetFoo(session: TROSession; conn: Connection): AnsiString;
var
svc: IMyService;
begin
svc := TMyService.Create(nil);
IROObjectActivation(svc).OnActivate(session.SessionID, nil);
try
Result := svc.GetFooImpl();
// or
Result := TMyService(svc).GetFooImpl();
finally
IROObjectActivation(svc).OnDeactivation(session.SessionID);
end;
end;
Whether or not you will need to use typecast for IROObjectActivation
depends on the declaration of IMyService
. Possibly, you don't need IMyService interface and you can just use IROObjectActivation
.