Hi, Rather than dumping all this information into a bug report I decided to write an email.
Here's a test program (attached) and a discussion of what goes wrong. Thanks again to Marco for explaining this to me and walking me through. For the line __globi := TTest.Create; a few things are generated: a) a call to TTest.Create b) a call to fpc_intf_assign, which in turn calls TTest._AddRef the call to Create is fine, nothing wrong with it. However, the call to _AddRef goes wrong. Now, heres what this actually looks like: This is the call to Create and to intf_assign is fine: call SYSTEM_TOBJECT_$__CREATE testl %eax,%eax je .L16 addl $44,%eax .L16: pushl %eax pushl $U_P$TESTII___GLOBI call fpc_intf_assign fpc_intf_assign calls AddRef from the VMT, which points to this code: WRPR_P$TESTII_TTEST_$_ITESTINT_$_2_$_SYSTEM_TINTERFACEDOBJECT_$___ADDREF: subl $44,(%esp) jmp SYSTEM_TINTERFACEDOBJECT_$___ADDREF Marco explained to me that this looks like tailcall optimization, however for one this doesn't even make sense here (because fpc_intf_assign has to do something else [check the destination and _release on it] after _addref); however this is the reason why the program bombs out. The call %eax in fpc_intf_assign pushes the correct return address within fpc_intf_assign onto the stack. Now, above code decrements it by 44 (0x2C). The new return address is now the following instruction from fpc_intf_incr_ref: mov (%eax), %eax Which segfaults immediately because %eax contains the return value of _addref (stdcall calling convention) which is 1 in this case. I don't really know where the problem is (ie, why the compiler generates this code), however this keeps reference counted interfaces from working at all. johannes -- http://www.sipsolutions.de/ GnuPG key: http://www.sipsolutions.de/keys/JohannesBerg.asc Key-ID: 9AB78CA5 Johannes Berg <[EMAIL PROTECTED]> Fingerprint = AD02 0176 4E29 C137 1DF6 08D2 FC44 CF86 9AB7 8CA5
program testii; {$MODE OBJFPC} uses baseunix; type ITestInt = interface(IInterface) end; TTest = class(TInterfacedObject, ITestInt) a,b,c,d,e,f,g,h:integer; end; var __globi: ITestInt; begin fpsleep(15); __globi := TTest.Create; end.
signature.asc
Description: This is a digitally signed message part