From: ciemo@bananapc.csd.sgi.com (Dave Ciemiewicz)
Subject: Re: Fortran problem on going from 4.0.1 to 4.0.5
Organization: Silicon Graphics, Customer Support Division
Date: Tue, 1 Sep 1992 01:15:08 GMT

In article <1992Aug31.161432.1@vaxa.strath.ac.uk>, cbas25@vaxa.strath.ac.uk writes:
|> The following fortran program illustrates a problem which has arisen on
|> going from IRIX 4.0.1 to IRIX 4.0.5.
|> When compiled under the first version of the operating system the program 
|> works correctly, and gives the correct results from both subroutines
|> (ONCE and DIFFER).  When compiled under 4.0.5 the program core-dumps at line
|> 42, unless the compilation is done with the keyword '-static'. 
|> 
|> A cutdown version in which the subroutine 'ONCE' is not called and the 
|> routine itself is not present, does run without core-dumping (when compiled 
|> without '-static') but it appears that the numbers in the second array (XS)
|> are not correctly held (all are either zero or very small numbers). 
|> 
|> My reading of the the Fortran manual pages leads me to believe that use
|> of the 'SAVE' directive in the subroutine DIFFER is the only requirement
|> for values to be retained on exit from a subroutine.
|> 

I've done some perusing of the Fortran 77 ANSI Standard and have come to the
conclusion that what you are attempting to do is not permitted by the standard.
I'll provide you with the following references from both the SGI Fortran 77 
manual and the Fortran 77 standard.  I'll also give you an technical
explanation which explains why what you are trying to do should not work.

From the SGI Fortran Manual, (Document# 007-0710-040):

	Rules for Use:

	- A SAVE statement without a list is treated as though all
	  allowable entities from the program unit were specified on the list.

	...

	Restrictions:

	Procedure names and dummy arguments cannot appear in a SAVE statement.

From the ANSI standard:

	8.9 Save Statement ...
		Dummy argument names ... must not appear in a SAVE statement.

		A SAVE statement without a list is treated as though it
		contained the names of all allowable itmes in that program
		unit.
		
	15.6.3 ...
		In a subroutine subprogram, the symbolic name of a dummy
		argument cannot appear in a ... SAVE ... statement.


Interpreting you example with respect to these statements:

|>       SUBROUTINE DIFFER
|>       SAVE
|>       DIMENSION XR(10)
|>       DIMENSION XS(10)
|>       ENTRY DIFF1 (XR)
|>       RETURN
|>       ENTRY DIFF2 (XS)
|>       RETURN
|>       ENTRY DIFF3 (I,J,D)
|>       write (*,*) i,j,xr(i),xs(j)  !Program fails here when '-static' not used
|>       D = XR(I) - XS(J)
|>       RETURN
|>       END 

XR and XS are dummy arguments for ENTRY DIFF1 and ENTRY DIFF2.  Since they
are dummy arguments, they are not allowable in a SAVE statement, thus they
will not be saved by the SAVE statement with an empty list.


Further, reading of the ANSI standard yields the following:

	15.7.4 ENTRY statement Restrictions ...

	If a dummy argument appears in an executable statement, the
	execution of the executable statement is permitted during the
	execution of a reference to the function or subroutine only if
	the dummy argument appears in the dummy aguement list of the
	procedure name referenced.  Note that the association of dummy
	arguments is not retuained between references to a function or
	subroutine.

Looking at your above example, XR is only valid when DIFF1 is called and
XS is only valid when DIFF2 is called.  Your use of XR and XS in the
ENTRY DIFF3 violates section 15.7.4 of the Fortran standard.

The reason is this: Fortran does not pass around copies of arrays in
function calls, it passes around an array reference.  Let's say I had the
code sequence:

	PROGRAM FOO

	CALL A
	CALL B
	CALL DIFF3(...)
	END

	SUBROUTINE A
	DIMENSION F1(10)
	CALL DIFF1(F1)
	RETURN
	END

	SUBROUTINE B
	DIMENSION F2(10)
	CALL DIFF2(F2)
	RETURN
	END

The arrays F1 and F2 in SUBROUTINES A & B would be locally allocated on the
call stack during the execution of their respective routines.  In fact, it
is highly likely that F1 and F2 would occupy the exact same address range on
the stack in this case.  The extents or life times of these arrays is limited
to the extent of time the SUBROUTINE is called.  As soon as the SUBROUTINE
returns, any reference to F1 (or F2) is invalid.  Your DIFF3 function is
trying to reference possibly invalid data.

The whole reason your program works when compiled -static is that the
arrays F1 and F2 would be kept around in static storage instead of being
automatically allocated on the stack during the invokation of A or B.
Also, the dummy variables XS and XR now have static allocation and so
their array references happen to keep around the addresses of the old
values.

|> I detected this anomaly in a larger program.  In this, the use
|> of three entry points to a subroutine is used to allow calculations
|> to be done on pairs of arrays selected from a much larger number than two.
|> Thus if there are n arrays the number of subroutine calls is 2*n rather than
|> n**2 (which is the case if both selected arrays are to be passed as 
|> parameters together in a single subroutine call.  

I'm sorry, I don't understand what you are trying to say here.

-- 

    __   * __   _  __  ___			
   /  \ / / /  / \/  \/   \ 	He was a man like any other man, however, not
  /    /  \/  /  /\  /    /	quite like any other man.
  \___/\__/\_/  /_/ / \__/	
	           *