Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29274 Discussions

Print statement generates weird error message

WSinc
New Contributor I
1,415 Views

It does execute the print statement, but then does this:

numgood= 1

forrtl: severe (40): recursive I/O operation, unit -1, file unknown

Image PC Routine Line Source

Console1.exe 004CC14A Unknown Unknown Unknown

Console1.exe 004C9898 Unknown Unknown Unknown

Console1.exe 0041B54A Unknown Unknown Unknown

Console1.exe 0041D935 Unknown Unknown Unknown

Console1.exe 0040CA83 _NUMGOOD 11 numgood.F90

Console1.exe 004111BE _MAIN__ 69 Sudoku_4.f90

Console1.exe 004D35A3 Unknown Unknown Unknown

Console1.exe 00475427 Unknown Unknown Unknown

Console1.exe 004752FF Unknown Unknown Unknown

kernel32.dll 7C817077 Unknown Unknown Unknown

The code is given below.
Seems pretty straightforward - - so I am puzzled....

integer*2 function numgood(level)

implicit NONE

integer*2 imove,level,ng

include "sud008.cmn"

ng=0

do imove=1,nomoves

if(goodmove(imove,level))then

ng=ng+1

endif

end do

print *,"numgood=",ng ! blows up here, or perhaps the next line.

numgood=ng

end function

0 Kudos
1 Solution
mecej4
Honored Contributor III
1,415 Views
> So, is there any way to avoid this problem later on?

Two simple ways, which I am sure you have already used a number of times:

1. Avoid I/O in functions that are going to be used in expressions instead of stand-alone invocations. Instead of writing out intermediate values or error messages, set the value of an integer, say "istat", to one of a set of values. You can either make istat an extra argument to the function, or keep in in a module that may be used by a helper/reporter function. This is how it is done in, e.g., IMSL. Compare also to errno in Unix.

2. Assign the function values to one or more temporary variables in the caller just before the I/O statement, and put the temporary variables in the I/O list expressions.

View solution in original post

0 Kudos
9 Replies
mecej4
Honored Contributor III
1,415 Views
I suspect that the line called out in the traceback

Console1.exe 004111BE _MAIN__ 69 Sudoku_4.f90

is an I/O statement that contains a reference to the function numgood. That would explain the complaint of recursive I/O.

What do you have in the COMMON block, and what does the statement on line 69 of sudoku_4.f90 say?
0 Kudos
Steven_L_Intel1
Employee
1,415 Views
I suspect that mecej4 is exactly on target. In particular, it would be a PRINT statement. Fortran disallows starting an I/O operation on a unit while another one is in progress on the same unit.
0 Kudos
WSinc
New Contributor I
1,415 Views
I don't see why whatMECEJ4 says is relevant.
First of all NUMGOOD is in quotes, so I am not creating a recursive call.
Secondly, the unit number it gives is -1.
I don't even know that those can exist. Aren't they supposed to be positive?
Third, I thought it was allowed in the current standard to be able
to print out a function value without generating a recursion.
At least with REAL and LOGICAL types, you can, so - - -
Why would this be any different?

I replied to this before, but I don't see that last one.

This subroutine works fine:
real*8 function krudd
krudd=1.0
print *,krudd
end

I think I found the problem:
NUMGOOD is also in the COMMON block,
so that probably confused the compiler.
I don't get a warning message, though,
telling me there's a conflict.
shouldn't it tell me?

Maybe the compiler guys should look at that?
0 Kudos
Steven_L_Intel1
Employee
1,415 Views
In our implementation, we use negative unit numbers for statements such as PRINT, TYPE, ACCEPT, etc. that don't have a unit number. In Fortran 2008, negative unit numbers are allowed when returned by OPEN(NEWUNIT=).

What we are asking you to look at is the procedure that calls function numgood. We suspect that there is something like:

print *, numgood(arg)

This would not be legal because function NUMGOOD also tries to do a print.
0 Kudos
mecej4
Honored Contributor III
1,415 Views
There seems to be some confusion between recursive I/O and recursive functions. Please consider this example, which invokes recursive I/O but has no recursive functions or subroutines in the source code.

[fortran]program recursiveIO
integer :: i
write(*,10)(i,isqr(i),i=5,10)
10 format(1x,2I4)

contains
   integer function isqr(ix)
      integer ix
      isqr=ix*ix
      write(*,*)' Function isqr : ',ix,isqr
      return
   end function isqr
end program recursiveIO
[/fortran]

Compile and run the program with traceback enabled, and then look at the description for Runtime Error-40 in the Intel Fortran documentation.
0 Kudos
WSinc
New Contributor I
1,415 Views
Well, this very simple test example does not cause any problems -

program test

x= test1(4)

print *,"x=",x

print *,test1(6)

read(*,*)

end

function test1(n)
test1=n
print *,"test1=",test1
e
nd

It runs to completion, with no error messages of any kind.
Doesn't think it's recursive I/O either.....
But YOUR EXAMPLE did generate the error message.
What's the difference?

0 Kudos
mecej4
Honored Contributor III
1,415 Views
Good counterexample!

However, given non-conforming code the behavior of the "processor" can be "implementation-dependent". In other words, not every violation of the language rules is required to be caught. And, as you know, not reporting an error is not the same as reporting that errors do not exist.

Try a small change to your second print line:

print *,test1(6),test1(-2)

Producing and looking at the assembly output from the compiler may throw light on the matter.

Briefly, with your second print statement, there is only one expression to print, and the compiler can choose to call the function and evaluate the expression(s) in the I/O list before starting the I/O.
0 Kudos
WSinc
New Contributor I
1,415 Views
HI -
sorry I don't know your first name.........

anyway, I did make the minor change you suggested,
and it did generate the "Recursive I/O" error mesage.

So, is there any way to avoid this problem later on?
I do occasionally need to print out the results of a
function output.
0 Kudos
mecej4
Honored Contributor III
1,416 Views
> So, is there any way to avoid this problem later on?

Two simple ways, which I am sure you have already used a number of times:

1. Avoid I/O in functions that are going to be used in expressions instead of stand-alone invocations. Instead of writing out intermediate values or error messages, set the value of an integer, say "istat", to one of a set of values. You can either make istat an extra argument to the function, or keep in in a module that may be used by a helper/reporter function. This is how it is done in, e.g., IMSL. Compare also to errno in Unix.

2. Assign the function values to one or more temporary variables in the caller just before the I/O statement, and put the temporary variables in the I/O list expressions.
0 Kudos
Reply