Recent

Author Topic: Does FPC fully support preserving the FOR variable when a GOTO or BREAK is used?  (Read 3190 times)

jamie

  • Hero Member
  • *****
  • Posts: 7402
As it states above.

 Using a FOR LOOP variable after the loop has terminated via Completion, GOTO, BREAK or even an Exception.

The question is this:

  If the Loop fully completes, is the VAR pointing to the last count when using GOTO, BREAK, Exit(VAR) etc, still valid or
is it undefined?

  From what I know it should still be defined in cases of possible early FOR loop termination, But should also be defined when For a LOOP completes with these TEST in the equation?

Is this correct and does EXIT(Loop Variable) also work here?

Jamie


The only true wisdom is knowing you know nothing

runewalsh

  • Full Member
  • ***
  • Posts: 106
If the loop terminates naturally (last iteration reaches end), the counter is undefined.
exit(counter) does not use counter outside of the loop, it assigns counter to result and exits.

jamie

  • Hero Member
  • *****
  • Posts: 7402
Then it does not follow the rules of Delphi.

   I have been using code like this and I see in the online docs that it does preserve the VAR if you BREAK or GOTO out of the loop early, but it does not state that the VAR can still be used if the BREAK or GOTO never gets reached, unless I missed something in the online DOCs :o;

  Technically, you still need to the Value to be valid in the case of the loop VAR being used following the loop, if a BREAK control is present in the control loop.

 This just came up when I was reviving some ported code which uses a few loops that way.


Code: Pascal  [Select][+][-]
  1.     For I := 0 To SOmething do If SomeArrayOFStates[I]=0 Then BReak;
  2.      If  SomeArrayOfStates[I]=0 then
  3.         WRiteln(' Found a blank in the list at index:',I:10 );
  4.  

That is an example of the use of the LOOP VAR in the code base.
 
 Tracking down some unrelated problem which isn't this but I saw this and got me wondering.

  I wanted to add that I found a discussion about this on the other guy's network and it reminded me of my own code base using it, so I took the time to ask here about it.

Jamie




 
« Last Edit: October 01, 2025, 01:41:01 am by jamie »
The only true wisdom is knowing you know nothing

LeP

  • Jr. Member
  • **
  • Posts: 66
From FPC Reference guide 2021:

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.

The compiler does not expliticly forbid jumping with a goto statement into a for loop block, but doing so will result in unpredictable behaviour.

So, the only missing case is the EXIT ... that should be cleared by a fpc developer.

In Delphi ther were a near discussion about that and it works in the same way (with exit too).

The value of index variable is valid only if the loop is interrupted. Or better, if the loop is completed the index variable should be considered not valid.

P.S.: in Delphi codebase ther are the same issues, the index is used outside the loop without any check.
I try a lot of test (in Delphi) in different way in "FOR" loops and all the time the index variable was valid. Not meaning if completed or interrupted.
I analyzed the assembly too.
But this should not be taken as TRUE because it may change in the next version of the compiler ....
« Last Edit: October 01, 2025, 02:10:33 am by LeP »

jamie

  • Hero Member
  • *****
  • Posts: 7402
That makes no sense really, because how do you know how the loop ended?

The way it's been in Delphi is, at least the way I used it, if you use early exit of control in the loop state via a GOTO, BREAK or exception and none of that actually happens, the Index is pointing to the last iterator.

  It's only when none of those are used is when the results are undefined.

 
  I use loops like that in many places just to determine the completion of the loop in cases where it may end early, its
easier for many times over using a WHILE statement.

 For now, I'll keep the code as is because I know it's not the problem where my code is doing some strange things.
 

The only true wisdom is knowing you know nothing

creaothceann

  • Full Member
  • ***
  • Posts: 223
Code: Pascal  [Select][+][-]
  1. for i := 0 to Something do  if (SomeArrayOfStates[i] = 0) then begin
  2.         WriteLn('found a blank in the list at index ', i:10);
  3.         break;
  4. end;
  5.  

Safer, smaller and slightly faster (no second check).

Thaddy

  • Hero Member
  • *****
  • Posts: 18515
  • Here stood a man who saw the Elbe and jumped it.
break and exit: loop variable is defined
goto: can have side effects but only when jumping in. Jumping out preserves the loop variable.
Remark section in the manual, which is correct:
https://www.freepascal.org/docs-html/ref/refsu58.html
« Last Edit: October 01, 2025, 06:32:44 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

LeP

  • Jr. Member
  • **
  • Posts: 66
That makes no sense really, because how do you know how the loop ended?

And how do you know that the loop started ?

There are some cases where the use of the index outside the loop without any check would cause issues.

I never used it, I use a boolean flag or the while loop if I need to know and use the index.

And now in Delphi with the inline variables it all more simple, no need to check.

But I think it’s a good practice not to use the index outside the loop, as it’s good practice not to use a global variable as an index.

Thaddy

  • Hero Member
  • *****
  • Posts: 18515
  • Here stood a man who saw the Elbe and jumped it.
Even for delphi it is documented that the value of a for to loop is undefined after the loop finished completely and defined for break and exit.
https://docwiki.embarcadero.com/RADStudio/Sydney/en/Declarations_and_Statements_(Delphi)#For_Statements
Any other assumptions can not be made. Again, the manual is pretty clear about that.
Question the manual?
This is a recurring issue and has been answered many times before. Suggest to close.
« Last Edit: October 01, 2025, 09:46:46 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

440bx

  • Hero Member
  • *****
  • Posts: 5894
Code: Pascal  [Select][+][-]
  1.     For I := 0 To SOmething do If SomeArrayOFStates[I]=0 Then BReak;
  2.      If  SomeArrayOfStates[I]=0 then
  3.         WRiteln(' Found a blank in the list at index:',I:10 );
  4.  
No matter what the answer is to your question, that code is wrong in all cases.

The reason is simple: it is not known how the "for" loop ended when the "if" is executed, therefore the value of "I" cannot be assumed to be defined (or, if you prefer, a predictable value.)

IOW, counter "I" has a predictable value only if the "for" loop ended as a result of the break but, its predictability _cannot_ be established using a condition that depends on it since the "origin" of its value is unknown.

For what that code is doing, the correct code would be:
Code: Pascal  [Select][+][-]
  1. For I := 0 To SOmething do
  2. begin
  3.   if SomeArrayOFStates[I]=0 Then
  4.   begin
  5.     WRiteln(' Found a blank in the list at index:',I:10 );
  6.  
  7.     break;
  8.   end;
  9.  
  10.   { not zero -> keep doing whatever it is, if anything, the loop is supposed to do }
  11. end;  
  12.  

Lastly, if all that's needed is to figure out if some array element is zero then a "while" loop seems to be a much better choice than a "for" loop (except for masochists... but, in that case there still better tools than a "for" loop... <chuckle>)

HTH.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 18515
  • Here stood a man who saw the Elbe and jumped it.
@440bx
He simply wants to know if the loop variable value can be relied upon on premature exit and the manual is very clear about that.
It is also the gazillionth' time this issue is raised. That doesn't bode well for capability of reading manuals or searching this forum.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12565
  • FPC developer.
@440bx
He simply wants to know if the loop variable value can be relied upon on premature exit and the manual is very clear about that.
It is also the gazillionth' time this issue is raised. That doesn't bode well for capability of reading manuals or searching this forum.

I don't know. His question is slightly different, and touches on the fact that a for-with-break-with-loopvar-dependency can't be optimized, so the loopvar is always there.

I'm inclined to say no it doesn't, but I'm not sure if I ever saw that hard in writing, and when break c.s. were introduced the comment was that it essentially changed the for to an unoptimized while..do under the hood.

Tests mean nothing of course, that might be implementation happenstance.

440bx

  • Hero Member
  • *****
  • Posts: 5894
After re-reading his statements, he wants to know if the presence of a statement such as break in the loop would cause the index variable to be reliable after the loop ends no matter how it ended.  The answer is: NO

The presence of a break (or goto) in the "for" is not enough.  The break or goto has to be executed, i.e, terminate the loop, for the index value to be reliable.

Using exit(index_variable) inside the loop should reliably return the value of the index variable as long as the "exit(index_variable)" is executed inside the loop.  exit(index_variable) is just shorthand for assigning the value of the index variable to "result" then executing "exit".

As others have already stated, if the loop completes, the value of the index variable is undefined.  It doesn't matter if there are break, gotos or black holes to China in the loop, as long as it completed normally, the value of the index variable is undefined.

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12565
  • FPC developer.
After re-reading his statements, he wants to know if the presence of a statement such as break in the loop would cause the index variable to be reliable after the loop ends no matter how it ended.  The answer is: NO

The presence of a break (or goto) in the "for" is not enough.  The break or goto has to be executed, i.e, terminate the loop, for the index value to be reliable.

A lot of opinion (to which I agree btw, I see no good reason for it to be any other way), but there is the detail point of actually finding documentation for it.

Because that would invalidate any claims that it "simply works".

Thaddy

  • Hero Member
  • *****
  • Posts: 18515
  • Here stood a man who saw the Elbe and jumped it.
Or better: falsification against verification. First take 1, second take the population. (Carl Popper)
When something seems to be xxx, it is definitely not true if a counter-argument is presented.

Stick to the manual. I'm off. ( just boring repeats and wishful thinking and sheer lazyness )
« Last Edit: October 01, 2025, 11:31:05 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

 

TinyPortal © 2005-2018