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

trapping bounds error

abhimodak
New Contributor I
1,190 Views

I got a legacy code and am quite perplexed that it works...I don't like the way it is and I will modify it. But I am worried that it has been working without any problems. Below is the code snippet.

The legacy code dimensionsan array in a common block. But it is done incorrectly (I think). As in the snippet below, array a is dimensioned 1. Thus, if the user gives value of anything greater than 1 to n, it is bounds error. Debug mode (i.e. /check:bounds) does trap it. However, in the release mode, it doesn't (as expected). But what I did not expect is that the value of a(n) written in unit 21 is 1.000000.

Is this behavior expected? i. e. when n = 5, a(5) is not valid; however, somehow a(5) is set to 1.0 and is written in the output file.

The legacy code uses array to read and write data from/to files (for say restarting from previous calculations). It does so through a do loop which goes over n=1,Ndim. I am mimicking that through use of reading n and seeing what happens when n > 1.

Abhi

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

Program Test_CommonDim

! Purpose: Test incorrect common block dimensioning.

Implicit None

Real(8) :: a

Common / MyTest / a(1)

Integer :: n

!###################

print *, "Give n"

Read *, n

!

a(n) = 1.0d0

Print *, "here"

write(21,*) a(n)

!

End Program Test_CommonDim

----------

0 Kudos
9 Replies
jimdempseyatthecove
Honored Contributor III
1,190 Views

Abhi,

(Steve may comment on this if I am incorrect)

Check your original application for all occurances of

COMMON /TheNameOfTheCommonBlockHere/ a(1)
(somewhere else)
COMMON /TheNameOfTheCommonBlockHere/ anything else here

I do not know the name of the common block in your application.

What you will likely find is something like

COMMON /SomeCommonName/ BIGBUF(1000)
(file you question
COMMON /SomeCommonName/ A(1)

The effect being a UNION between A(1) and BIGBUFF(1) and subsiquently should you index beyond 1 inA you will index into BIGBUFF at the same index. The effect being A(1) in the declaration statesA is an array and "I, the coder, assume responsibility for all indexes beyond the declared size". Older version of Fortran did not assume the responsibility of bounds checkingfrom the programmer.

Jim Dempsey

0 Kudos
TimP
Honored Contributor III
1,190 Views
A long time ago, it was fairly common practice, but not entirely portable, to play games like this with inconsistent definitions of COMMON blocks.
Varying COMMON block lengths don't play well with OpenMP, as the OpenMP standard disallows it. It requires special linker support, not present in the linkers used with ifort, for OpenMP libraries to handle it in the way certain applications expected.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,190 Views

The original poster's legacy code may have been written with inconsistent (by desigh)definitions of COMMON blocks as stated in my reply and restated in Tim18's reply. As tim18 points out, there may be additional problems when porting to OpenMP (although in your legacy applicaiton I do not think the inconsistancies relating to OpenMP apply).

This said, the recommended cure for the OpenMP problem will very likely be the very cure for most of your problems.

This will be to convert your COMMON blocks into module data declarations. This exercise may be difficult to do for many legacy applications where there are many instances of multiply layed out named COMMON blocks as well as EQUIVALENCE data. The conversion effort (common to module) may be difficult and time consuming without an apparent payback (in performance). The payback comes in two ways: 1) isolation of problems that may occure in multi-threaded version of your application, and 2) increasing maintainability of your code.

Jim Dempsey

0 Kudos
abhimodak
New Contributor I
1,190 Views

Many thanks, Jim and Tim.

I did suspect "another common block definition" but in my 'hunting' so far I have not found one. The common block is in an include file and that include file gets used.

However, what is happening with my snippet? Why is a(5) "assigned" value of 1 when a(5) does not exist? Pardon my naivity in asking this question...

Abhi

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,190 Views

Abhi,

a(1) exists at some memory location. Memory exists beyond a(1),unless a(1) assigned address at upper most end of virtual address range (not likely).


Although a(5) is not within the range of valid subscript for a(n) the memory address produced by indexing a(5) is a valid address (when bounds checking turned off). Something else resides there and this is the value you see. If you were to write to a(5) you would modify the other variable's data.

Jim Dempsey

0 Kudos
abhimodak
New Contributor I
1,190 Views

Hi Jim

Thanks for your answer. I 'intuitively' thought of your explantionand it is good to have an authoritative stamp on it...My unease has been a(5) producing a valid address but, of course, I had seen it happenas someone uses a(101) and gets b(1)stomped oversince a is declared to a(100).

The legacy code is playing a dangerous game and I am astonished (may be stupidly so) that it has been successful as it has been around for a decade or more..

Abhi

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,190 Views

Abhi,

Abstraction simile

Think of memory as a parking lot. From one perspective use you have all the lines painted down for the customers and employees to use during business hours. Early in the morning though, it is temporarily used by UPS or some other parcel package delivery service as a rendezvous point for package exchange, the delivery vans parked over the lines with back-ends together. Then at other times (e.g. Walmart practice) large personal vehicles (e.g. Winnebago travel vehicles) as well as buses may park in the lot, again over the lines. As long as the users of the parking lot pay attention to the vehicles, instead of only the lines ,then there is no problem with multiple use of the parking lot.

Old legacy code may have been written 30 years ago when memory was constrained. Not wanting to have to rewrite code written from multiple places (and introduce new errors in the process) the technique chosen was to examine the code for potential memory conflict and if none exists, overlay the address space for different uses.

It is easy to say today when all systems have 2GB or more RAM "My gosh! What were they thinking!". In the early days of Fortran you may have had 32KB of RAM to work with (and some times less depending on how old the legacy code was). It was clearly understood by programmers that memory had to be overlayed with different templates and the programmer had the responsibility to be careful about variable usage (conflict avoidence). Todays programmers assume a variable declared is alwaysdeclared in unused memory and will be the exclusive usefor that variable until the variable expires (goes out of scope or is deleted). This assumption is a false assumption when managing code written under a different set of programming rules.When dealing with legacy fortran code (code with COMMON and EQUIVALENCE) you must assume the responsibility of assuring non-conflicting use of memory. This should be a good modivating force to convert to use of MODULES early on in the program enhancement or port.

Jim Dempsey

0 Kudos
bgmchenry
Beginner
1,190 Views

One other item not mentioned...in the legacy code, that code snippet may have been used as a way to creat a pointer to the memory location. The common was used as temp storage and that's why various different units have different sizes, etc.

I believe in the ole mainframe daze common memory was sequential, so the 'trick' really didn't harm anything as long as you didn't exceed the max size of the common block.

Brian

0 Kudos
abhimodak
New Contributor I
1,190 Views

Jim, many thanks, once again,for putting it in a nice story.

Brian, the code snippet does exactly as used in the legacy code. All I changed was variable names. I appreciate you looking at it from a different angle.

Abhi

0 Kudos
Reply