Error in documentation of EXIT command

Microsoft Windows
Post Reply
User avatar
MigrationUser
Posts: 336
Joined: 2021-Jul-12, 1:37 pm
Contact:

Error in documentation of EXIT command

Post by MigrationUser »

19 Nov 2015 15:19
Aacini


The documentation of EXIT command given at https://ss64.com/nt/exit.html indicate that a FOR command placed in a subroutine can be terminated with EXIT /B command. However, this not works if the loop is a FOR /L one. The only way to break a FOR /L is with plain EXIT command, and the way to avoid the termination of the whole cmd.exe session is invoking the "subroutine" via cmd /C "%~F0" :sub trick instead of CALL, and start the batch file with: IF "%~1" EQU :sub GOTO sub

Last edited by Aacini (19 Nov 2015 15:31)

----------------------------

#20 Nov 2015 11:38
Simon Sheppard


It works for me, heres a simple example of exit /b with FOR /L

Code: Select all

@echo off
setlocal

call :sub
echo all done
goto:eof

:sub
For /l %%G in (1,1,5) do (echo %%G & exit /b)
Echo end of the subroutine we will never get here
goto :eof
Note that it is exiting the whole subroutine, not just the FOR command, so the last echo statement is never displayed.
In PowerShell we have a proper break-loop command https://ss64.com/ps/break.html

----------------------------

#20 Nov 2015 12:47
npocmaka


Try this (with small numbers you wont see the difference):

Code: Select all

@echo off
setlocal

call :sub
echo all done
goto:eof

:sub
For /l %%G in (1,1,10000000) do (echo %%G & exit /b)
Echo end of the subroutine we will never get here
goto :eof
:)

----------------------------

#20 Nov 2015 13:08
jeb


Or see the cause with this sample

Code: Select all

echo ON
For /l %%G in (1,1,3) do (
  echo %%G
  exit /b
)
Output (without empty lines)

Code: Select all

C:\temp>For /L %G in (1 1 3) do (
echo %G
 exit /b
)
C:\temp>(
echo 1
 exit /b
)
1
C:\temp>(
echo 2
)
C:\temp>(
echo 3
)
The execution of the commands in the loop is stopped, but the loop itself loops until the end count is reached.
Currently I'don't understand why the EXIT/B isn't displayed by the ECHO ON.

Btw.
This also affects the (GOTO) 2>NUL technic (I'm not able to find the Dostips topic)
As the FOR /L loop can't be immediatly stopped without EXIT, the stack analyzer can hang at this point.
But the effects are strange here, as it's still possible to discover the call stack but the loop will still iterate later.

Last edited by jeb (20 Nov 2015 13:18)

----------------------------

#20 Nov 2015 16:16
Aacini


The real problem with this point appear when we want to break an infinite loop, but I didn't wanted to present this example before because it could cause discussions that have no relation with the core point of this problem:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

call :sub
echo all done
goto:eof

:sub
set i=0
For /l %%G in () do (
   set /A i+=1
   echo !i!
   if !i! equ 5 exit /b
)
Echo end of the subroutine we will never get here
goto :eof
If the EXIT /B would break the FOR /L the control would return to the main program after 5 iterations, but this never happens...

This problem may also affect other situations with loops with few iterations; see: https://stackoverflow.com/questions/337 ... batch-file In that code the loop could be changed by a normal "(1,1,10)" one and the program still give wrong results...

Last edited by Aacini (20 Nov 2015 16:31)

----------------------------

#20 Nov 2015 19:20
jeb
Aacini wrote:

If the EXIT /B would break the FOR /L the control would return to the main program after 5 iterations, but this never happens...

... In that code the loop could be changed by a normal "(1,1,10)" one and the program still give wrong results...
I can't confirm this, just tested with W7x64. I changed the loop to (1,1,10)

Code: Select all

1
2
3
4
5
all done
The point about unbreakable infinite loops is still valid.

Last edited by jeb (20 Nov 2015 19:22)

----------------------------

#20 Nov 2015 20:28
Simon Sheppard


Great explanations!

I've added a paragraph about this to https://ss64.com/nt/exit.html

Thanks all

----------------------------

#21 Nov 2015 03:37
Aacini
jeb wrote:
Aacini wrote:

If the EXIT /B would break the FOR /L the control would return to the main program after 5 iterations, but this never happens...

... In that code the loop could be changed by a normal "(1,1,10)" one and the program still give wrong results...
I can't confirm this, just tested with W7x64. I changed the loop to (1,1,10)

Code: Select all

    1
    2
    3
    4
    5
    all done
The point about unbreakable infinite loops is still valid.
@jeb: I think you mixed up two different paragraphs of my reply. When I wrote "In that code" I meant the one posted at the link placed immediately before that phrase. "That code" contain this segment:

Code: Select all

REM -- NOTE: Infinite loop, breaks out when root directory is reached --
REM -- or makefile is found                                           --
for /L %%n in (1,0,10) do (
That code fails because the 'exit /b 2' command placed inside the FOR /L loop does not break it, so the subroutine never ends. What I said is that the original "for /L %%n in (1,0,10) do (" infinite loop could be changed by a normal "(1,1,10)" one and the program still give wrong results because the loop is not break when required, although in this case the subroutine ends after 10 iterations...
Post Reply