I am working with a legacy Fortran project converted from CVF and have encountered an error caused by a local variable in one subroutine becoming corrupted by a write statement in another. After much searching I traced the apparent problem to the following WRITE statement:
SUBROUTINE OUTPUT DOUBLE PRECISION XDUM(12) CHARACTER LINEO*264 . . WRITE(LINEO(21:30),'(F9.2)') XDUM(1)
The value of local variable DSTMOM appears correct in a different subroutine when the WRITE statement has not been executed:
If the WRITE statement is executed with XDUM(1) being written to LINEO, DSTMOM changes to:
Is there anything wrong with the WRITE statement, or could the problem be something else? I will try Steve's idea from another post of rebuilding the project from scratch for the Intel compiler, but am not sure if that would help solve this or not. Thanks for any suggestions!
This sort of problem is sometimes caused by incorrect argument passing. You'd need to construct a self-contained test case for anyone to be able to comment further.
Since it is a project converted from CVF, it lacks some of the diagnostics enabled with new projects. Try creating a new project and adding the sources to it, and see if you get any build errors. Then run the debug configuration and see if there are run-time errors.
Thank you Steve. I will try creating a new project as you suggest. I figure that the write statement itself is probably not the problem, but only a way of manifesting another problem that may be difficult to find!
>>I am working with a legacy Fortran project converted from CVF...
One potential source of a problem like this is when the person performing the conversion improperly mucks up the COMMON declarations. For example, removing unused variables (or adding variables) in one of the named commons and not doing the same in all other uses of the same named common.
Very difficult error to find. It may be caused by a mismatch length in character or array arguments of some subroutine or function. Interface checking can detect thoses errors.
Probably the problems existed before but was masked by different memory locations.
Try to switch your watch window to hexadecimal to try to see if characters are written in the memory location of DSTMOM.
>>The value of local variable DSTMOM appears correct in a different subroutine...
The debugger has a single focus. When you are in subroutine FOO, local variables in FUDYDUDY in watch are meaningless (should be greyed out).
If you are trying to examine the local variables of the CALLer, then, using the Call Stack window, double click on the caller to set the focus to the caller's stack.
I thank all of you for your comments. I was hoping that perhaps there was something obviously wrong with the WRITE statement, or perhaps the subroutine containing the WRITE statement would most likely be the location of the source of the problem to focus on. I have since created a new Intel project and am in the process of reviewing about 60 errors that were produced in the compilation (mainly 6633 and 6401).
If the other subroutine (in which you inspected and displayed DSTMOM) is not part of the call chain between the main program and OUTPUT, what you are seeing is perfectly normal behavior, and there is no memory corruption or other bug to worry about. Local variables are, hmm, LOCAL, are allocated on the stack (unless they are arrays that you put on the heap), and are undefined when the subprogram that they belong to is not active, even though the debugger may show values for them at that time.
One has to take the displayed values with a pinch of salt. Take, for example, the displayed value of DSTMOM(7,7). The improbable value 1.060997895581449d-313 (for a 64-bit real variable) is, most probably, two consecutive 32-bit integers -- yes, the two integers 2 and 5. That is, the same 8 bytes on the stack that were formerly occupied by two simple integers (local variables) in one subroutine are now being interpreted as a double precision number in another subroutine. You can see this for yourself as follows. Compile the following program with debugging enabled and set for x86 target (if you are using CVF, you have to use /automatic as well), start it in the debugger, and place a breakpoint on the line containing "x = ...". When the break point is hit, look in the Locals pane, and observe the value displayed for x (note: it has not been set to a value at this point).
program duped implicit none call sub1() call sub2() contains subroutine sub1() implicit none integer ij(2) ij(1) = 2 ij(2) = 5 return end subroutine subroutine sub2() implicit none double precision x x = 3.14157265d0 return end subroutine end program