* * *

Author Topic: Using Add method in class derived from generic list fails horribly.  (Read 611 times)

BrainChemistry

  • Jr. Member
  • **
  • Posts: 65
I feel I'm missing something. Anyway, I need a hint. :(

I have a generic object list (specialized TFPGObjectList fro unit FGL) and I have a class which derives from this generic object list. Using the inherited Add function within methods fails (desastrously).

Pseudo code:
Code: Pascal  [Select]
  1. ...
  2. TMyObjectList = specialize TFPGObjectList<TMyObject>;
  3.  
  4. ...
  5.  
  6. TMyAdvancedObjectList = class(TMyObjectList)
  7.   function Add(AObject: TMyObject): Word;
  8. end;
  9. ...
  10. Implementation
  11. ...
  12. function TMyAdvancedObjectList.Add(ASomething: Something): Word;
  13. var
  14.   AMyObject: TMyObject;
  15. begin
  16.   AMyObject := TMyObject.Create;
  17.   AMyObject.Field1 := ASomething;
  18.   inherited Add(AMyObject); // here the compiler screws up/system freezes, really ugly
  19. ...
  20. end;
  21.  

Well, this also happens if I change the method name ('Add') not to be the same as the ancestors (which means inherited can be left off). It is therefore not related to the inherited keyword.

Why would the AMyObject instance not just be added to the list, but rather everything gets screwed up?

Thanks for any help and hints in advance.

Lazarus 1.8.4, FPC 3.0.4.

jamie

  • Hero Member
  • *****
  • Posts: 908
Re: Using Add method in class derived from generic list fails horribly.
« Reply #1 on: October 30, 2018, 02:24:33 am »
I noticed you did not override the prior ADD method..

 I can only assume since I don't see the code for that one that it is a Virtual declaration ?

 I am only speculating at this time.

BBasile

  • Sr. Member
  • ****
  • Posts: 432
Re: Using Add method in class derived from generic list fails horribly.
« Reply #2 on: October 30, 2018, 03:05:13 am »
Yeah maybe the code is wrong but the compiler shouldn't freeze the system so there still a valid FPC issue there.

Thaddy

  • Hero Member
  • *****
  • Posts: 7087
Re: Using Add method in class derived from generic list fails horribly.
« Reply #3 on: October 30, 2018, 09:53:19 am »
Yeah maybe the code is wrong but the compiler shouldn't freeze the system so there still a valid FPC issue there.
Well, then he should at least attempt to give a compilable example.
I could reconstruct those fragments into:
Code: Pascal  [Select]
  1. {$mode objfpc}{$H+}
  2. uses fgl;
  3.  
  4. type
  5.   TMyObject = class
  6.   end;
  7.  
  8.   TMyObjectList = specialize TFPGObjectList<TMyObject>;
  9.  
  10.   TMyAdvancedObjectList = class(TMyObjectList)
  11.     function Add(AObject: TMyObject): Word;
  12.   end;
  13.  
  14. function TMyAdvancedObjectList.Add(AObject: TMyObject): Word;
  15. begin
  16.   result := inherited Add(AObject);
  17. end;
  18.  
  19. var
  20.   a:TMyAdvancedObjectList;
  21.   b:TMyObject;
  22. begin
  23.   a:= TMyAdvancedObjectList.Create;
  24.   a.FreeObjects := true;
  25.   b:=TMyObject.create;
  26.   a.add(b);
  27.   a.free;
  28. end.

Which has no issues at all....
- Note add is a function! and the compiler warns... he could have known.
- Note override is not necessary in objfpc mode.
« Last Edit: October 30, 2018, 11:37:45 am by Thaddy »
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

BrainChemistry

  • Jr. Member
  • **
  • Posts: 65
Re: Using Add method in class derived from generic list fails horribly.
« Reply #4 on: October 30, 2018, 12:36:59 pm »
Thanks for your replies.

@jamie: As mentioned by Thaddy, ADD is not virtual.

@Thaddy:
I adapted your code to reflect the structure my code has. But basically it is correctly derived, thanks for that.
Code: Pascal  [Select]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses fgl;
  6.  
  7. type
  8.   TMyObject = class
  9.   tag:integer;
  10.   end;
  11.  
  12.   TMyObjectList = specialize TFPGObjectList<TMyObject>;
  13.  
  14.   TMyAdvancedObjectList = class(TMyObjectList)
  15.     function Add(SomeTag: Integer): Word;
  16.   end;
  17.  
  18. function TMyAdvancedObjectList.Add(SomeTag: Integer): Word;
  19. var
  20.   AObject: TMyObject;
  21. begin
  22.   AObject := TMyObject.Create;
  23.   AObject.tag := SomeTag;
  24.   inherited Add(AObject);
  25.   result := SomeTag;
  26. end;
  27.  
  28. var
  29.   a:TMyAdvancedObjectList;
  30.   //b:TMyObject;
  31.   c: Integer = 1;
  32. begin
  33.   a:= TMyAdvancedObjectList.Create;
  34.   a.FreeObjects := true;
  35.   //b:=TMyObject.create;
  36.   a.add(c);
  37.   a.free;
  38. end.
  39.  

Now someting really strange happens and I hope you can reproduce it (and it is not bc. my system is already too screwed :D).

If you run the program from Lazarus (F9) everything seems to run smooth and it runs through.
If you place a break point in line 34 (right before calling the add method, and then proceed stepwise by F7, you run in a SIGSEV right at line 24.

Can anybody confirm this behaviour? And what am I doing wrong?


Thaddy

  • Hero Member
  • *****
  • Posts: 7087
Re: Using Add method in class derived from generic list fails horribly.
« Reply #5 on: October 30, 2018, 01:13:45 pm »
As I wrote Add is here a function and not a procedure. That function is also used internally in the class. It relies on returning the value just before the new element.
What you do is not possible. The result from add should be the result from inherited add!
Code: Pascal  [Select]
  1. result :=inherited Add(AObject);
and not some fancy other result.

What you can do is introduce and "add" with another name, like "MyAdd" that calls add, but make sure the result from add stays valid.
Also note that overload would not help if the parameter list is equal (even if the function result differs as in your case)
« Last Edit: October 30, 2018, 01:42:09 pm by Thaddy »
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

BrainChemistry

  • Jr. Member
  • **
  • Posts: 65
Re: Using Add method in class derived from generic list fails horribly.
« Reply #6 on: October 30, 2018, 02:11:57 pm »
Thanks for your reply.

Quote
- Note add is a function! and the compiler warns... he could have known.
Quote
That function is also used internally in the class. It relies on returning the value just before the new element.
It is clear to me that Add is a function. The problem is rather that it is used internally. I wasn't aware of this. The compiler did never warn for me (default settings).                                                                                     

Quote
What you can do is introduce and "add" with another name, like "MyAdd" that calls add, but make sure the result from add stays valid.

I tried this (see code below). Same SIGSEGV as before. Why? :(

Code: Pascal  [Select]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses fgl;
  6.  
  7. type
  8.   TMyObject = class
  9.   tag:integer;
  10.   end;
  11.  
  12.   TMyObjectList = specialize TFPGObjectList<TMyObject>;
  13.  
  14.   { TMyAdvancedObjectList }
  15.  
  16.   TMyAdvancedObjectList = class(TMyObjectList)
  17.     //function Add(SomeTag: Integer): Word;
  18.     function MyAdd(SomeTag: Integer): Word;
  19.   end;
  20.  
  21. //function TMyAdvancedObjectList.Add(SomeTag: Integer): Word;
  22. //var
  23. //  AObject: TMyObject;
  24. //begin
  25. //  AObject := TMyObject.Create;
  26. //  AObject.tag := SomeTag;
  27. //  inherited Add(AObject);
  28. //  result := SomeTag;
  29. //end;
  30.  
  31. function TMyAdvancedObjectList.MyAdd(SomeTag: Integer): Word;
  32. var
  33.   AObject: TMyObject;
  34. begin
  35.   AObject := TMyObject.Create;
  36.   AObject.tag := SomeTag;
  37.   Add(AObject);
  38.   result := SomeTag;
  39. end;
  40.  
  41. var
  42.   a:TMyAdvancedObjectList;
  43.   //b:TMyObject;
  44.   c: Integer = 1;
  45.  
  46. begin
  47.   a:= TMyAdvancedObjectList.Create;
  48.   a.FreeObjects := true;
  49.   //b:=TMyObject.create;
  50.   a.MyAdd(c);
  51.   a.free;
  52. end.  
  53.  

correa.elias

  • New member
  • *
  • Posts: 12
Re: Using Add method in class derived from generic list fails horribly.
« Reply #7 on: October 30, 2018, 02:26:05 pm »
Since you talking about lazarus screwing your system, it happend to me when using an antivirus software. Looks like compilers and antivirus dont mix well...

Thaddy

  • Hero Member
  • *****
  • Posts: 7087
Re: Using Add method in class derived from generic list fails horribly.
« Reply #8 on: October 30, 2018, 02:56:34 pm »
It does not SIGSEV here. What versions of FPC and Lazarus are you using?
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

jamie

  • Hero Member
  • *****
  • Posts: 908
Re: Using Add method in class derived from generic list fails horribly.
« Reply #9 on: October 30, 2018, 05:43:09 pm »
for what it's worth, I have an app that I started to develop using the 64 bit install. I have a thread in it that talks to serial ports and what happen a couple
of times when some actions went wrong in the thread while running the app under debug mode, it actually blue screened my Windows 10, something I have
never seen before..
 
  The same app in the 32 bit install works fine while debugging if an error takes place in that code so I have continued to work on the project in the
32 bit mode for now and later I will compile a version of it in the 64 bit target.

BrainChemistry

  • Jr. Member
  • **
  • Posts: 65
Re: Using Add method in class derived from generic list fails horribly.
« Reply #10 on: October 31, 2018, 12:31:28 pm »
Thanks all for your replies!

@correa.elias: Well, I never experienced troubles with antivirus software. I can imagine antivirus interference if you... well, try to develop a virus...  :o

@Thaddy:
Quote
Lazarus 1.8.4, FPC 3.0.4.
Windows 8.1 64 bit.

I can reproduce the SIGSEGV reliably by adding a break point to line 48, then go stepwise (by F7), receiving the SIGSEGV at line 37. The example program runs perfectly well (without SIGSEGV) if I run it without any break points. Maybe the debugger is causing this here?

In contrast to that my real application code leads to a freeze (even without a break point).

for what it's worth, I have an app that I started to develop using the 64 bit install. I have a thread in it that talks to serial ports and what happen a couple
of times when some actions went wrong in the thread while running the app under debug mode, it actually blue screened my Windows 10, something I have
never seen before..
 
  The same app in the 32 bit install works fine while debugging if an error takes place in that code so I have continued to work on the project in the
32 bit mode for now and later I will compile a version of it in the 64 bit target.


Well, to be honest, from the example code I just get a SIGSEGV, nothing too bad.
If I do the same in my real application it fails by freezing my system. Although I'm not sure why this is, some low level libraries are loaded at this point and I think that this contributes to the worse behaviour.

Thaddy

  • Hero Member
  • *****
  • Posts: 7087
Re: Using Add method in class derived from generic list fails horribly.
« Reply #11 on: October 31, 2018, 01:23:40 pm »
I can not reproduce the SIGSEV with either 3.2.0 or FPC trunk and Laz trunk
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus