TDelphiWebScript.Destroy inconsistent behavior

Issue #24 closed
Алек Невашедело created an issue

in the destructor the inherited Destroy is invoked before self-destructions. Firstly, this is not usual practice to do so: usual are -- in ctors call inherited in first place, to ensure initialization of inherited members, and in destructors -- call inherited after finalization of of self members. Is TDelphiWebScript.Destroy designed against the rule on a purpose? -- because if not, I've spent several hours investigating AV-usage of freed object on the simple case:

procedure exscript();
var myUnit:TdwsUnitA;//symadd override
begin
 dwsc:=TDelphiWebScript.Create();
myUnit:=TdwsUnitA.Create(dwsc);//dwsc owned this unit, let him manage lifetime
dwsc.AddUnit(myUnit);
//do stuff

FreeAndNil(dwsc);//And here is problem! 
//althought TDelphiWebScript stores it's unit list
//as list of interfaces, but because of TdwsUnit is TComponent descendant -- reference
//counting does not work! So calling inherited destructor in   first place decommits all 
//owned objects, including myUnit! Subsecquent    FConfig.Free; causes AV, since it calls
// _intfClear on freed myUnit object, while derefencing IdwsUnit links in the unit list.
end;

so, let the code looks like this

destructor TDelphiWebScript.Destroy;
begin

   FCompiler:=nil;
   FConfig.Free;
   FExtensions.Free;
   inherited;
   FLock.Free;
end;

Comments (3)

  1. Eric Grange repo owner

    Hmm, using AddUnit directly for a TdwsUnit will result in an incoherent internal state (Script reference will not be defined or may even reference another TDelphiWebScript instace), you should be using "myUnit.Script := dwsc;" instead.

    I will see about locking down that usage.

  2. Eric Grange repo owner

    Also inherited as to be called before FConfig is freed to support the following scenario where the TdwsUnit is bound to the Script (and similar variants in the design-time editor).

       s:=TDelphiWebScript.Create(nil);
       try
          u:=TdwsUnit.Create(s);
          u.Script:=s;
       finally
          s.Free;
       end;
    
  3. Log in to comment