Recent

Author Topic: set issue causing range error  (Read 6565 times)

jack616

  • Sr. Member
  • ****
  • Posts: 268
set issue causing range error
« on: February 10, 2016, 05:16:47 pm »
I'm having a problem with a set test causing a range error in a console application.
It can be reproduced by the .lpr file below.

I don't know if I'm doing something I shouldn't or if it's reproducable elsewhere.
It functions as expected if the set test is true but gives the range error when false.
Can anyone else see the issue?

 Settings:
 lazarus v1.6RC2
 Target - defaults win7-64
 Project options - range check on
 Run parameters empty

 Debugging enabled:
      charout[1] or charout[2] prints "found" and waits for a key
      charout[3] or charout[4] (ie not in set) causes "RunError(201)" in lazarus
      (range error)
Also reproduces when the executable is run from command line.

Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$MODE DELPHI}
  4.  
  5. {$IFDEF WINDOWS}
  6.  {$APPTYPE CONSOLE}
  7. {$ENDIF}
  8.  
  9. uses sysutils,classes;
  10.  
  11. Type
  12.   TalphaSet = 'A'..'Z';
  13.   TcharSet = set of TalphaSet;
  14.  
  15. var
  16.  thisChar: TcharSet;
  17.  charout: string;
  18.  
  19. procedure initProg;
  20. begin
  21.   thisChar := ['A','B','C','D','E','F'];
  22.   charout := 'AB12';
  23. end;
  24.  
  25. BEGIN
  26. initProg;
  27. if ( charout[3] in thisChar ) then  // change charout here
  28.    writeln('Found')
  29.   else
  30.    writeln('Not Found');           // this is not reached
  31.   readln;
  32. END.
  33.  
  34.  

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4467
  • I like bugs.
Re: set issue causing range error
« Reply #1 on: February 10, 2016, 05:40:01 pm »
I guess it should be :
Code: Pascal  [Select][+][-]
  1. type
  2.   TcharSet = set of AnsiChar;
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

Nitorami

  • Sr. Member
  • ****
  • Posts: 496
Re: set issue causing range error
« Reply #2 on: February 10, 2016, 06:36:09 pm »
Yes. The '1' is not part of your TAlphaSet so it can never be in a TCharSet. If you try

Code: Pascal  [Select][+][-]
  1. if '1' in thisChar then ...
  2.  

you will get a range check error at compile time already.

jack616

  • Sr. Member
  • ****
  • Posts: 268
Re: set issue causing range error
« Reply #3 on: February 12, 2016, 12:25:45 pm »
I guess it should be :
Code: Pascal  [Select][+][-]
  1. type
  2.   TcharSet = set of AnsiChar;

Thank you JuaManninen - I don't think so but
can you explain why you do?

I have to say I'm a little disturbed by the lack of response to this.


Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: set issue causing range error
« Reply #4 on: February 12, 2016, 01:53:21 pm »
What Juha did was explain to you the proper use of Pascal sets.
Here's an example that works as you expect:
Code: Pascal  [Select][+][-]
  1. // proper code
  2. program project1;
  3. {$IFDEF FPC}{$MODE DELPHI}{$H+}{$ENDIF}
  4. {$APPTYPE CONSOLE}
  5. type
  6.   TCharset = set of AnsiChar;
  7. var
  8.  thisChar: TcharSet;
  9.  charout: AnsiString;
  10.  
  11. procedure initProg;
  12. begin
  13.   thisChar := ['A','B','C','D','E','F'];
  14.   charout := 'AB12';
  15. end;
  16.  
  17. begin
  18. initProg;
  19. if ( charout[3] in thisChar ) then  // change charout here
  20.    writeln('Found')
  21.   else
  22.    writeln('Not Found');           // of course this is reached
  23.   readln;
  24. end.
  25.  
  26.  

You will get a range error because there are no numerics in your original range. get it now?
If you put '12' there, it is not in the range of the TYPE.

You need to declare a variable or typed const that is a subset of the type range you want to test.
This is very basic Pascal and excellently explained in the manuals.


« Last Edit: February 12, 2016, 04:31:39 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

jack616

  • Sr. Member
  • ****
  • Posts: 268
Re: set issue causing range error
« Reply #5 on: February 13, 2016, 11:17:59 am »
Thaddy - I think you are missing the point.
You have re-written my code ignoring the salient point.
Tcharset is not a set of ansichar.

Tcharset is a set of 'A'..'Z'
Or put another way - Tcharset is a set of sub-sets.
That is the issue I am asking about. It causes a  runtime crash if used.
(Not a compile time crash as suggested)
This is not acceptable compiler behaviour IMO.
An "if" statement should not be able to crash at runtime under any circumstances.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: set issue causing range error
« Reply #6 on: February 13, 2016, 11:39:56 am »
You are missing the point that in your case TCharset is the TYPE, not a set of char.
But anyway, here's a slightly very slightly changed example that does work under Delphi and FPC trunk:
Code: Pascal  [Select][+][-]
  1. program project4;
  2. {$APPTYPE CONSOLE}
  3. {$IFDEF FPC}{$MODE DELPHI}{$ENDIF}
  4. uses
  5.   sysutils,
  6.   classes;
  7.  
  8. Type
  9.   TalphaSet = 'A'..'Z';
  10.   TcharSet = set of TalphaSet;
  11.  
  12. var
  13.  thisChar: TcharSet;
  14.  charout: string;
  15.  
  16. procedure initProg;
  17. begin
  18.   thisChar := ['A','B','C','D','E','F'];
  19.   charout := 'AB12';
  20. end;
  21.  
  22. begin
  23. initProg;
  24. if ( charout[3] in thisChar ) then  // change charout here
  25.    writeln('Found')
  26.   else
  27.    writeln('Not Found');           // this is definitely reached in 3.1.1-r33091
  28.   readln;
  29. end.
  30.  

That's basically the same code as you entered, so the bug if any is already fixed.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4467
  • I like bugs.
Re: set issue causing range error
« Reply #7 on: February 13, 2016, 11:44:17 am »
It is logical. A Pascal set is typically a bitmap where one bit represents one element.
Only as many bits are reserved as are needed by the range defining the set.
Then the operations can be implemented as very fast CPU bit manipulation instructions (AND, OR, XOR etc.). I think Pascal still has one of the best syntax for Set Theory math.
  https://en.wikipedia.org/wiki/Set_theory

You could have done directly:
Code: Pascal  [Select][+][-]
  1. if ( charout[3] in ['A','B','C','D','E','F'] ) then
which uses AnsiChar as a range. Fortunately the compiler has a range check feature and all range related bugs are found easily.

For bigger ranges like Integer the set is not a bitmap. It is optimised some other way. For example:
Code: Pascal  [Select][+][-]
  1. if ( MyInt in [100,1000,10000] ) then

[Edit]
Quote
... does work under Delphi and FPC trunk:
Then they have added an extra check, making the code slightly less optimized. Maybe it is in mode Delphi only, I don't know. FPC forum section or mailing list may be a better place to ask.
« Last Edit: February 13, 2016, 11:52:08 am by JuhaManninen »
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: set issue causing range error
« Reply #8 on: February 13, 2016, 11:53:31 am »
It is logical.

But currently his code compiles, as I demonstrate with almost the exact same code, under trunk.
I still tnink what you and I wrote before, but it works.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

jack616

  • Sr. Member
  • ****
  • Posts: 268
Re: set issue causing range error
« Reply #9 on: February 15, 2016, 03:01:59 pm »
So it's just a bug then. OK fair enough.

Perhaps I should emphasize for anyone reading this that compiling with V3.0 (IDE 1.6RC2)
without the range check option left on creates code that runs but simply ignores the error.
As it is not spotted at design time by the compiler - testing with range check on will not flag
it up until you actually run with invalid data.

As many people may have downloaded this version of lazarus it is worth noting as it may not
be just the use of sets that caused it - I can find no reference to a bug fix so don't know the
actual cause. Other situations may then cause the issue.

Do we know when lazarus is likely to be released with an updated FPC ?




JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4467
  • I like bugs.
Re: set issue causing range error
« Reply #10 on: February 15, 2016, 03:37:36 pm »
So it's just a bug then. OK fair enough.

It is not a bug. It is a feature. Sets have behaved like that always IIRC.
I understood the behaviour was changed in FPC trunk. You can ask technical details in FPC mailing list or forum category.

There are many situations where an error in code shows up only at run time. That's why it is important to keep all compiler checks on when testing the code.

As many people may have downloaded this version of lazarus it is worth noting as it may not
be just the use of sets that caused it - I can find no reference to a bug fix so don't know the
actual cause. Other situations may then cause the issue.

What other situations you are referring to?
« Last Edit: February 15, 2016, 03:39:16 pm by JuhaManninen »
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

jack616

  • Sr. Member
  • ****
  • Posts: 268
Re: set issue causing range error
« Reply #11 on: February 16, 2016, 01:23:22 pm »
Not only a bug but a critical one.
If it wasn't the behaviour wouldn't have  changed and the behaviour itself would not allow
faulty data to occur unchecked - which it does - at runtime. I can't think of a better definition of a  bug.
You tell me what situations can occur with randomly ignoring faulty data.

I don't know it is just a set issue - the example program I generated merely displays
the fault as I found it and since we don't know what was changed to stop it we
don't know where else it may happen or why. There is at least one other range error
problem reported in the bug tracker this week that was cured. It may not be relevant
but it's certainly suspicious.

IMO lazarus needs an urgent update now others have reproduced it AND seen it go away with
a later version of FPC. Thaddys post suggests it is cured - so something fundamental changed.

I'm trying to be diplomatic about it but claiming it isn't a bug it's a feature is plain dangerous.


Cyrax

  • Hero Member
  • *****
  • Posts: 836
Re: set issue causing range error
« Reply #12 on: February 16, 2016, 01:55:38 pm »
...
For bigger ranges like Integer the set is not a bitmap. It is optimised some other way. For example:
Code: Pascal  [Select][+][-]
  1. if ( MyInt in [100,1000,10000] ) then
...

Nope. FPC (recent revision of trunk) gives this warning
Quote
Warning: range check error while evaluating constants (10000 must be between 0 and 255)
and if value of MyInt is larger than 255, the in clause will always gives false as an its result. Thus clauses enclosed this if clause won't be executed at all.

There is no (yet) support for huge sets (for values larger than 256) in FPC.

See attached demo project for another example.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8757
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: set issue causing range error
« Reply #13 on: February 16, 2016, 02:01:42 pm »
Use Classes.TBits instead for sets with >256 elements. FCL-STL set types are also capable for handling non-ordinal types.

Nitorami

  • Sr. Member
  • ****
  • Posts: 496
Re: set issue causing range error
« Reply #14 on: February 16, 2016, 02:48:15 pm »

I feel this is neither a bug nor a feature, it is the correct behaviour of the compiler.

Your type TAlphaSet explicitly excludes numbers, probably for a good reason (which I do not know). If the program checks for the presence of a '1' in a set of TAlphaChar, it is quite right to assume that something went wrong and throw a range check error.

And yes, the compiler can spot the issus at compile time already but only if is can detect that you try to find apples in oranges. Such is obviously the case in

Code: Pascal  [Select][+][-]
  1. if '1' in thisChar...
but not in
Code: Pascal  [Select][+][-]
  1.  if charout[3] in thisChar...


 

TinyPortal © 2005-2018