Recent

Author Topic: Assigning interface  (Read 1044 times)

egsuh

  • Hero Member
  • *****
  • Posts: 1738
Assigning interface
« on: December 19, 2022, 11:18:12 am »
Hi,  I have defined interfaces like following.

Code: Pascal  [Select][+][-]
  1. unit Interface1
  2. interface
  3. type
  4.      IDBAccess = interface
  5.           //...
  6.      end;
  7. var
  8.      DBAccess: IDBAccess;
  9. implementation
  10. // ...
  11. end.
  12.  
  13. unit dModule1
  14. interface
  15. uses Interface1;
  16. type
  17.      Tdm1 = class (TDataModule, IDBAccess)
  18.          .....
  19.      end;
  20. implementation
  21. procedure Tdm1.DataModuleCreate(Sender:TObject);
  22. begin
  23.      IDBAccess := Self;
  24. end;
  25. // ...
  26. end.

But this calls SIGSEV error when closing the application. I've read somewhere that interfaces do reference counting and when there are no objects it try to destroy implementing object. Does the error occur because of either interface or object try to destroy the object which was destroyed already by the other?

Or, does my way of using interface have serious problem? I did not have any problem when I declared interface field (i.e. DBAccess here) within class.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12644
  • FPC developer.
Re: Assigning interface
« Reply #1 on: December 19, 2022, 11:21:36 am »
The cardinal rule of interfaces is that typically you create the class and immediately assign it to an interface and never mix variables that are class references with variables that are interface references on the same object.

As such that is probably not very compatible with the VCL that is mostly class reference based.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6315
  • Compiler Developer
Re: Assigning interface
« Reply #2 on: December 19, 2022, 10:12:20 pm »
The cardinal rule of interfaces is that typically you create the class and immediately assign it to an interface and never mix variables that are class references with variables that are interface references on the same object.

As such that is probably not very compatible with the VCL that is mostly class reference based.

Any descendant of TComponent (which includes TDataModule) by default reimplements _AddRef and _Release to not do any reference counting (except if VCLComObject is assigned).

@egsuh: please provide a full example that shows your problem and not merely snippets.

egsuh

  • Hero Member
  • *****
  • Posts: 1738
Re: Assigning interface
« Reply #3 on: December 21, 2022, 03:24:18 am »
Quote
]@egsuh: please provide a full example that shows your problem and not merely snippets.

I tried to write a small project replicating the exceptions but they failed. My original project have dozens of units so it's not practical to post it here. I'll search for some reason myself and post it if I find the reason or other relevant issue.

ccrause

  • Hero Member
  • *****
  • Posts: 1093
Re: Assigning interface
« Reply #4 on: December 21, 2022, 06:32:58 am »
Code: Pascal  [Select][+][-]
  1. type
  2.      Tdm1 = class (TDataModule, IDBAccess)
  3.          .....
  4.      end;

Are you perhaps setting the AOwner parameter when creating your TDataModule? This could result in the AOwner also freeing the TDataModule instance.

egsuh

  • Hero Member
  • *****
  • Posts: 1738
Re: Assigning interface
« Reply #5 on: December 21, 2022, 10:10:44 am »
Quote
Are you perhaps setting the AOwner parameter when creating your TDataModule? This could result in the AOwner also freeing the TDataModule instance.

That's what I have thought. TDataModule is auto-created by application. But I could not replicate the exception with a small project.

I reviewed my original program again, and I found the definitions are :

Code: Pascal  [Select][+][-]
  1. interface
  2. type
  3.      IICommon = interface
  4.           // ....
  5.      end;
  6.  
  7.      IDBAccess = interface(IICommon)
  8.           //...
  9.      end;
  10. var
  11.      DBAccess: IDBAccess;
  12. implementation
  13. // ...
  14. end.
  15.  
  16. unit dModule1
  17. interface
  18. uses Interface1;
  19. type
  20.      Tdm1 = class (TDataModule, IICommon, IDBAccess)
  21.          .....
  22.      end;


There are vars of both types of IICommon and IDBAccess.

The exception does not occur if I write both of :

Code: Pascal  [Select][+][-]
  1. procedure Tdm1.DataModuleCreate(Sender:TObject);
  2. begin
  3.      IDBAccess := Self;
  4. end;
  5.  
  6. procedure Tdm1.DataModuleDestroy(Sender:TObject);
  7. begin
  8.      IDBAccess := nil;
  9. end;
  10.  

 

TinyPortal © 2005-2018