Recent

Author Topic: Bug in Verify Method  (Read 799 times)

Grahame Grieve

  • Full Member
  • ***
  • Posts: 110
Bug in Verify Method
« on: October 19, 2020, 08:29:41 am »
There's some obscure bug in FPC that I haven't been able to reproduce except deep inside my rather large server, but I'm documenting it here in case some one else runs into it and can further characterise it.

The bug manifests only when running with the debugging option "verify method calls" is on.

I create a generic, Tlist<X> where X is some object. At some stage, this is the result of a method. As long as the execution point is in the metbod, the result is fine. But as soon as you exit the method, doing anything with the result causes an invalid typcast, even though the debugger says that nothing has changed about the TList<X> before and immediately after exiting the method.

I can't figure out how to work around this - I cannot use verify method calls (even though it found one other real bug for me)

Actually, freebee: there's another bug in Verify method Calls: if you call  the method

TCollectionNotifyEvent<T> = procedure(ASender: TObject; constref AItem: T; AAction: TCollectionNotification)
    of object;

under some obscure set of conditions I haven't figured out to characterise but might include the declare T being abstract, while AItem being a sub-class of it, then verify methods says that T is not valid, even though it is. But it only say it's not valid under some conditions

I can't reproduce either of these in a simple application. (not for lack of trying)

PascalDragon

  • Hero Member
  • *****
  • Posts: 2405
  • Compiler Developer
Re: Bug in Verify Method
« Reply #1 on: October 19, 2020, 09:38:12 am »
Would you at least be able to show excerpts of your code that triggers the problem? Your descriptions don't help much there...

Grahame Grieve

  • Full Member
  • ***
  • Posts: 110
Re: Bug in Verify Method
« Reply #2 on: October 19, 2020, 11:50:16 am »
No, the first of these 2 is something else than what I thought. I think that the compiler must be generating 2 parallel definitions for the same generic, because it really is the same class, but according to assertions, it's not the case.

FPC 3.3.1.

And in answer to your question... I really don't know what to post. There's 3 million lines of code here, and I don't know which ones are the relevant ones.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2405
  • Compiler Developer
Re: Bug in Verify Method
« Reply #3 on: October 19, 2020, 01:06:13 pm »
No, the first of these 2 is something else than what I thought. I think that the compiler must be generating 2 parallel definitions for the same generic, because it really is the same class, but according to assertions, it's not the case.

That is indeed the case. If you have a TList<LongInt> in UnitA and a TList<LongInt> in UnitB then they are different specializations that are compatible to each other.

And in answer to your question... I really don't know what to post. There's 3 million lines of code here, and I don't know which ones are the relevant ones.

You have the compile time error or runtime exception somewhere. Show a bit of the code where this happens and the involved variable and type declarations. Maybe also in which units these are declared.

jamie

  • Hero Member
  • *****
  • Posts: 3784
Re: Bug in Verify Method
« Reply #4 on: October 19, 2020, 04:03:05 pm »
From the description of code working within the method and the method returning some object not working tells me that an object living on the stack has been past back and at some point the stack will get changed thus changing the object..

  That Is what I summarize from the post.

The only true wisdom is knowing you know nothing

Grahame Grieve

  • Full Member
  • ***
  • Posts: 110
Re: Bug in Verify Method
« Reply #5 on: October 19, 2020, 08:59:04 pm »
> If you have a TList<LongInt> in UnitA and a TList<LongInt> in UnitB then they are different specializations that are compatible to each other.

I'm not sure how to read this. The context suggests that you are saying that they generate duplicate code..?

jamie

  • Hero Member
  • *****
  • Posts: 3784
Re: Bug in Verify Method
« Reply #6 on: October 19, 2020, 11:25:25 pm »
> If you have a TList<LongInt> in UnitA and a TList<LongInt> in UnitB then they are different specializations that are compatible to each other.

I'm not sure how to read this. The context suggests that you are saying that they generate duplicate code..?

Different in the sense they are define in other units which is common.

and yes, that would most likely generate another copy of all the methods etc...

aren't generics fun ? bloat bloat ..

but there are ways to shrink things down since you now know this. build a class to inherit from that is not generics dependent and only implement what is needed for the generic type parts and that saves a lot there.

 also, I believe if you use some CLASS methods it gets reduced..

The only true wisdom is knowing you know nothing

Grahame Grieve

  • Full Member
  • ***
  • Posts: 110
Re: Bug in Verify Method
« Reply #7 on: October 19, 2020, 11:53:40 pm »
I understand that generics cause bloat, but having duplicate generics isn't just boat, it's a recipe for bugs everywhere, since parameters aren't compatible.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2405
  • Compiler Developer
Re: Bug in Verify Method
« Reply #8 on: October 20, 2020, 10:09:32 am »
> If you have a TList<LongInt> in UnitA and a TList<LongInt> in UnitB then they are different specializations that are compatible to each other.

I'm not sure how to read this. The context suggests that you are saying that they generate duplicate code..?

That's exactly what I'm saying. If UnitA and UnitB don't know each other then there is no way for them to know that one of them already has a sufficient implementation. There is currently no optimization pass inside the compiler to rectify this when linking the final binary (just like this wasn't the case in Delphi either originally, they improved this with later versions).

I understand that generics cause bloat, but having duplicate generics isn't just boat, it's a recipe for bugs everywhere, since parameters aren't compatible.

They are compatible enough as far as the compiler is concerned. Though if there are indeed user visible bugs for this (which can be, cause generics are a big, complicated topic) I'm happy to fix them (cause for the user this should be transparent), but I need reproducible examples that show the problem.

Grahame Grieve

  • Full Member
  • ***
  • Posts: 110
Re: Bug in Verify Method
« Reply #9 on: October 20, 2020, 02:30:44 pm »
Well, I have no choice but to go chasing it, but it would wonderful to have a stack when the type violation occurs. The stack is empty, and I'm still trying to walk into the problem to find out where it is.

Laz 2.1.0, FPC 3.3.1, FpDebug, Optimization = 1, debugging = all on

I'll keep looking.

Grahame Grieve

  • Full Member
  • ***
  • Posts: 110
Re: Bug in Verify Method
« Reply #10 on: October 20, 2020, 03:56:13 pm »
I did fix it by replacing all the uses of a generic with a specialised class. I couldn't figure out what about the pattern made it be a problem, but it's fixed by the definition of this type

  TFhirCodeSystemConceptMapW = TFslMap<TFhirCodeSystemConceptW>;

in https://github.com/grahamegrieve/fhirserver/commit/6153b479fe981cff16b5089cab1b0d11d1e3a696. Unfortunately it's buried in whitespace changes, but at some point, closing the server down, the code would call .free on what absolutely is a valid TFslMap<TFhirCodeSystemConceptW>, and I'd get invalid typecast - after it has already assigned it no problem. note that everything about the code works except for the assertion code that checks that the type is correct.


I guess that this set of symptoms, and the fact that replacing the generic with a speciallised class (did a search and replace, so no other changes) means that it's one of your "indeed user visible bugs for this" but I've done nothing characterise it further, except that every time I've found anything like this, there's generics with type parameters that are abstract classes.


 

TinyPortal © 2005-2018