2-19 MEMORY MANAGEMENT
***********************
(Thanks to Craig Burley for making subtle points clear)
Memory allocation problems create nasty bugs, of the kind that appear
and disappear without apparent reason, and may trash computations
without causing error messages.
Size of memory representation for different data types
------------------------------------------------------
The FORTRAN 77 standard (2.13) imposes few restrictions on the
representation of variables in memory, it specifies only the relative
sizes of some of the data types.
The standard explicitly avoids comparing the size of characters and
non-character data and defines two unrelated measurement units,
character storage unit (CSU) and numeric storage unit (NSU).
The sizes specified are:
Data type Size
---------------- -----
INTEGER 1 NSU
REAL 1 NSU
LOGICAL 1 NSU
DOUBLE PRECISION 2 NSU (consecutive)
COMPLEX 2 NSU (consecutive)
CHARACTER*n 1 CSU * n (consecutive)
Because the relative size of all the numeric data types is specified
in the standard, operations like EQUIVALENCE, associating different
sets of variables in CALL/SUBROUTINE pairs, and re-declarations of
COMMON blocks, will give standard results on numeric data.
In other words, the standard ensures that aliasing operations
(provided character types are not present) will give standard
results without imposing impossible restrictions on the
implementation of storage.
For example:
INTEGER int
REAL x
EQUIVALENCE (int , x)
That way you can read a REAL variable and manipulate it in
a portable way using the almost universal two's complement
representation of integers.
Array types
-----------
Arrays are very important, and usually take up most of the memory
used by a program. No wonder different array types were developed
and are implemented:
Constant - array dimensions are specified by constants that
can be computed at compile-time.
Adjustable - are passed to a procedure; dimensions are passed
with other variables from the calling procedure.
Assumed size - are passed to a procedure; upper-bound of last
dimension is unknown to the called procedure,
programmer is responsible for not getting out
of array bounds.
Automatic - (Fortran 90) array dimensions are not compile-time
constants, and may change on each invocation.
Allocatable - (Fortran 90) array dimensions may be determined
at run-time.
Where in the program memory is allocated?
-----------------------------------------
Is memory always allocated top-down?
------------------------------------
How much you can count on unSAVEd static memory?
------------------------------------------------
PROGRAM AUTSAV
CALL SUB(0)
CALL SUB(1)
END
SUBROUTINE SUB(FLAG)
INTEGER
* FLAG, ARRAY(100)
IF (FLAG .EQ. 0) THEN
ARRAY(100) = 123456789
ELSE
IF (ARRAY(100) .EQ. 123456789) THEN
WRITE (*,*) ' AUTOSAVING PROBABLY IMPLEMENTED '
ELSE
WRITE (*,*) ' AUTOSAVING NOT SUPPORTED '
ENDIF
ENDIF
RETURN
END
Call-by-reference vs. copying in/out
------------------------------------
The proper way to check what argument-passing mechanism your compiler
uses, is to look in the assembly language listings it produces.
Aho, Sethi and Ullman in the dinosaur book (p. 427) have a small
Pascal program that gives different results if the parameter-passing
mechanism is call-by-reference or copy-restore (copy-in copy-out).
A Fortran version of their program is non-standard (FORTRAN 77 standard,
section 15.9.3.6, Restrictions on Association of Entities) discusses
exactly such programs and explicitly prohibit them, probably so that
both parameter-passing mechanisms would give the same result.
Being non-standard the following program can't be guaranteed to work
properly (or at all), but anyway it's interesting.
PROGRAM CPINOUT
INTEGER i
COMMON i
i = 1
CALL SUB(i)
IF (i .EQ. 0) WRITE(*,*) ' Call-by-reference was used '
IF (i .EQ. 2) WRITE(*,*) ' Copy-restore was used '
END
SUBROUTINE SUB(i)
INTEGER i, j
COMMON j
i = 2
j = 0
RETURN
END
Another program explicitly prohibited by 15.9.3.6 is:
PROGRAM CPINOUT
INTEGER i, j
i = 1
j = 1
CALL SUB1(i,i)
CALL SUB2(j,j)
IF ((i .EQ. 0) .AND. (j .EQ. 2))
* WRITE(*,*) 'Call-by-reference was used '
IF (i .EQ. j) WRITE(*,*) 'Copy-restore was used '
END
SUBROUTINE SUB1(i,j)
INTEGER i, j
i = 2
j = 0
RETURN
END
SUBROUTINE SUB2(i,j)
INTEGER i, j
j = 0
i = 2
RETURN
END
Return to contents page