Recent

Author Topic: For variable being read after loop... Any way to get an error or warning on it?  (Read 13310 times)

DarioGL

  • New member
  • *
  • Posts: 7
We are facing an issue and its that in some parts of our legacy code the variable of a for loop is consulted after the loop ends normally. This has an undetermined behaviour (as the for variable is undefined after the loop).

Is there a way to enable a warning/error/hint so it warns us of this?

Code: Pascal  [Select][+][-]
  1. var
  2.   i, res: Integer;
  3. begin
  4.   res := i; // Gives warning
  5.  
  6.   for i := 0 to 10 do ;
  7.  
  8.   res:= i; // No warning
  9.  

MarkMLl

  • Hero Member
  • *****
  • Posts: 7725
We are facing an issue and its that in some parts of our legacy code the variable of a for loop is consulted after the loop ends normally. This has an undetermined behaviour (as the for variable is undefined after the loop).

Is there a way to enable a warning/error/hint so it warns us of this?

Submit a bug report. The problem is that in the example you gave the control variable i was defined (by Wirth) as having an undefined value, while if there was a break in it (added by Borland post-Wirth) then i would have a defined value.

My own opinion is that this presents a strong argument for being able to define the control variable in a local scope:

Code: Pascal  [Select][+][-]
  1. var
  2.   res: Integer;
  3. begin
  4.   for i: integer := 0 to 10 do ;
  5.  
  6.   res:= i; // Error here
  7.  

however there would still be no error on

Code: Pascal  [Select][+][-]
  1. var
  2.   i, res: Integer;
  3. begin
  4.   res := i; // Gives warning
  5.  
  6.   for i: integer := 0 to 10 do ;
  7.  
  8.   res:= i; // No error here
  9.  

since Pascal is quite happy with variables that hide others of the same name in an outer scope.

Put another way: I sympathise, even if I can be of little help.

MarkMLl

MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Eugene Loza

  • Hero Member
  • *****
  • Posts: 729
    • My games in Pascal
I don't think it's easy to give a warning there, because sometimes the loop variable can be properly defined after the loop. The documentation states that:
Quote
The value of the loop variable is undefined after a loop has completed or if a loop is not executed at all. However, if the loop was terminated prematurely with an exception or a break or goto statement, the loop variable retains the value it had when the loop was exited.
I.e. loop variable can be defined under some circumstances and it's not always so easy to tell if those circumstances always take place or not.
I must admit I'm not a big fan of such uncertainty too, but I believe there are several places where things like that can happen and the most reliable way is to audit&refactor all of them manually.
I.e. you can find all "for" loops in your files (in Lazarus Shift+Ctrl+F or Menu->Search->Find in Files; note "Whole words only" checkbox) and make sure that the variable is not used after the loop (again just searching may help to speed up the process; also Lazarus has a convenient "highlight" feature, just select the loop variable name and it will highlight it in the remaining code; note that the latter won't work too well if the loop variable name is short like "i" as highlighting doesn't have "words only" checkbox (or I couldn't find it) and hence will highlight all "i"s in all words on the screen, making it harder to read).
My FOSS games in FreePascal&CastleGameEngine: https://decoherence.itch.io/ (Sources: https://gitlab.com/EugeneLoza)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11782
  • FPC developer.
I don't think it's easy to give a warning there, because sometimes the loop variable can be properly defined after the loop. The documentation states that:

If you have a for without gotos or break, you can mark the variable as unitialized after the loop, and the normal warning system should take over.

Eugene Loza

  • Hero Member
  • *****
  • Posts: 729
    • My games in Pascal
Quote
you can mark the variable as unitialized
Oh, that would be a good thing for myself too. I wonder how to do that? I know about Initialize(...) and Default(...) from System, but couldn't find anything like Uninitialize or Deinitialize.

Or do you mean Finalize(...)? For some reason I've thought it leaves the variable initialized. Just checked and it doesn't seem to create compiler warnings for using the variable after Finalize.
My FOSS games in FreePascal&CastleGameEngine: https://decoherence.itch.io/ (Sources: https://gitlab.com/EugeneLoza)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11782
  • FPC developer.
Quote
you can mark the variable as unitialized
Oh, that would be a good thing for myself too. I wonder how to do that?

I meant in the liveliness analysis in the compiler

MarkMLl

  • Hero Member
  • *****
  • Posts: 7725
Quote
you can mark the variable as unitialized
Oh, that would be a good thing for myself too. I wonder how to do that?

I meant in the liveliness analysis in the compiler

So that would presumably again be a bug report, either to request that that be implemented or to highlight a case where the compiler is overlooking it.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5691
  • Compiler Developer
Quote
you can mark the variable as unitialized
Oh, that would be a good thing for myself too. I wonder how to do that?

I meant in the liveliness analysis in the compiler

So that would presumably again be a bug report, either to request that that be implemented or to highlight a case where the compiler is overlooking it.

That would be an extension/improvement of the DFA (Data Flow Analysis). But yes, it warrants a bug report, so that especially FPK knows what's missing (as he is the one mainly working on DFA).

MarkMLl

  • Hero Member
  • *****
  • Posts: 7725
That would be an extension/improvement of the DFA (Data Flow Analysis). But yes, it warrants a bug report, so that especially FPK knows what's missing (as he is the one mainly working on DFA).

It would certainly be a good way of shutting me up: I know that I'm a PITA in this area :-)

More seriously: I agree, and am slightly ashamed that I didn't think of suggesting this approach myself.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Joanna

  • Hero Member
  • *****
  • Posts: 1105
We are facing an issue and its that in some parts of our legacy code the variable of a for loop is consulted after the loop ends normally. This has an undetermined behaviour (as the for variable is undefined after the loop).

Is there a way to enable a warning/error/hint so it warns us of this?

Code: Pascal  [Select][+][-]
  1. var
  2.   i, res: Integer;
  3. begin
  4.   res := i; // Gives warning
  5.  
  6.   for i := 0 to 10 do ;
  7.  
  8.   res:= i; // No warning
  9.  
I don’t see any problems with this code. It does not matter If the value of the loop variable “i“ becomes undefined, the “res” variable will retain the value last assigned to it which in this case would be 10.
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

440bx

  • Hero Member
  • *****
  • Posts: 4570
It does not matter If the value of the loop variable “i“ becomes undefined, the “res” variable will retain the value last assigned to it which in this case would be 10.
No, that is _not_ the case.

because of line 8, the variable "res" will end up having whatever value "i" has after exiting the loop which is _undefined_.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Khrys

  • Jr. Member
  • **
  • Posts: 98
I don’t see any problems with this code. It does not matter If the value of the loop variable “i“ becomes undefined, the “res” variable will retain the value last assigned to it which in this case would be 10.

According to the ISO Pascal standard6.8.3.9 For-statements  (page 63 of the .pdf):

Quote from: ISO/IEC 7185:1990
After a for-statement is executed, other than being left by a goto-statement, the control-variable shall be undefined.

Whenever it happens to work, it's due to implementation details and is still undefined behaviour.

Eugene Loza

  • Hero Member
  • *****
  • Posts: 729
    • My games in Pascal
So, I've done a simple test. For loop behavior heavily depends on optimization level asked from the compiler. E.g. in Default build mode it writes a pointer to the variable and therefore the loop variable will indeed keep the value it was last assigned during the loop.

However -O4 (didn't test others) in turn uses registers instead of a pointer to gain speed (and is right to do so :D). As a result the variable has its default value (i.e. undefined). See first screenshot attached. Unfortunately it doesn't show the warning - which this topic is about :)

Moreover, it's smart enough to notice that the loop doesn't do anything and skips the loop entirely showing a compiler-time warning about uninitialized variable. See the second screenshot.

What happens under the hood can be seen in Assembler window.
My FOSS games in FreePascal&CastleGameEngine: https://decoherence.itch.io/ (Sources: https://gitlab.com/EugeneLoza)

Joanna

  • Hero Member
  • *****
  • Posts: 1105
Quote
for i := 0 to 10 do ;
I didn’t notice the semicolon after the “do”  ::)

I have previously requested that the code tools not put semicolon after the “do” But to no avail. Ridiculous code that does nothing should not even compile in my opinion... ;D It’s a big flaw in fpc to rely upon programmers to notice and remove a semicolon placed where it doesn’t belong. I have had this break my code several times. Why on earth can’t it be fixed?

Nonetheless I just tested it and it gave 10 just as predicted. I’m using no optimization.
« Last Edit: August 01, 2024, 04:40:56 pm by Joanna »
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

MarkMLl

  • Hero Member
  • *****
  • Posts: 7725
I didn’t notice the semicolon after the “do”  ::)

I have previously requested that the code tools not put semicolon after the “do” But to no avail. Ridiculous code that does nothing should not even compile in my opinion... ;D It’s a big flaw in fpc to relay on programmers to notice and remove a semicolon placed where it doesn’t belong. I have had this break my code several times. Why on earth can’t it be fixed?

That's absolutely nothing to do with FPC, if anything that's a Codetools issue and TBH I agree that it's far too agressive with inseriontion: I try to turn off as many as possible.

Quote
Nonetheless I just tested it and it gave 10 just as predicted. I’m using no optimization.

None of us give a damn. Wirth defines that i at that point has no predictable value, and the fact that a specific implementation with specific code before it and a specific optimisation level seems to result in a particular value is totally irrelevant.

Marco's suggestion is the best we'll see.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018