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

Strange behavior in f77 subs using V9

pecan204
Beginner
1,105 Views

Can someone please comment.

I converted an older workspace in CVF to IVF. All compiles but when running I get unexpected behavior when calling a couple of subroutines. I have now spentdays debugging these two issues.

The first is: After second call to the function THERM it does not recognize data fa = -1.0. I later added the the FA=. Now it works. But why did it not work consistently before?

FUNCTION THERM (ID,ARG,FAOLD,DUMMYP)

IMPLICIT DOUBLE PRECISION (A-H,O-Z)

DATA FA/-1.D0/

X=ARG

FA = -1.0

The second is:After the second call to sub flocal the variable n1 changes to 10. What is doing this and what else can I inspect to see why and fix it?

SUBROUTINE FLOCAL (IGET,SS,EROR,JCXCNT)

IMPLICIT DOUBLE PRECISION (A-H,O-Z), INTEGER (I-N)

As soon as the second call enters sub here, N1 changes to 10. The first call it was set to 1 seen below. The second pass imediately changes to 10 without being set by a variable.

DO 10 I=1,NTBL

IF(ITAB(I).EQ.6969)IBOATTAB=I

10

CONTINUE

IF (NPASS.LE.0) THEN

XPASS=.FALSE.

N1=KKINDS(1,1)

Thanks for any help.

Ken

0 Kudos
10 Replies
jimdempseyatthecove
Honored Contributor III
1,105 Views

Ken,

I am not sure on your 1st question, but for the second question it would seem that you are expecting N1 to have been saved from the prior call to FLOCAL. To have persistance you need to declare N1 with the SAVE attribute (or compile with /Qsave to save all variables).

Your first question error may also be corrected with /Qsave.

Also, consider using in THERM

REAL(8), SAVE :: FA = -1.D0

And using in FLOCAL

INTEGER, SAVE :: N1 = (initial N1 to 0, -1, 9999, whatever)

Since your programhas problems of uninitialized variables (not saved), you may find it fruitful to compile and debug with the runtime check for uninitialized variables.

Jim Dempsey

0 Kudos
Les_Neilson
Valued Contributor II
1,105 Views

Ken,

First, all of your "debug" configurations shouldhave all of the warnings set on, especially bounds checking. The problem with variable FA sounds suspiciously like an out of bounds overwite of memory somewhere.

The problem with N1 : If N1 is a local, unsaved variable of subroutine FLOCAL then it will be allocated storage automatically on entering FLOCAL, the contents of that storage will be whatever is in there at the time - there is no automatic initialisation of variables. If the first thing you do with N1 is an assignment to itthen the previous contents are immaterial.

hth

Les

0 Kudos
pecan204
Beginner
1,105 Views

Thank you Les/Jim, Very informative answers. I'll try that right now.

I also just used the locals view and see there is a N1STT equal to 10 that is comming from an include common block. But how could it be written to N1? There is no equivalence.

0 Kudos
Les_Neilson
Valued Contributor II
1,105 Views

If N1 is truly independent of N1STT then it is just coincidence.

One of the problems of common blocks is out-of-bounds errors. An array in one common with some code "array(I) = something"where the value of I is out of the bounds of the array could overwrite data either in the same common block or in the next common block.

Most of us "older" programmers will have seen this before.

Les

0 Kudos
Steven_L_Intel1
Employee
1,105 Views
You have a coding error not apparent in the snippets you post. I suggest enabling "Generate Interface Blocks" (/gen-interface) and "Check Interface Blocks" (/warn:interface) to see if there are calling mismatches.
0 Kudos
pecan204
Beginner
1,105 Views

Thanks Steve,

I did have success in getting it running with /Qsave and now to your recomendation I am looking for an interface error. /gen-interface and /warn came up with an error calling a charcter function with the *. But I am not that familiar with that call. Do you know what is the correct way?

Function below.

Ken

CHARACTER *(*) FUNCTION SHIFTBL(CHSTR)

CHARACTER *(*) CHSTR

INTEGER I, J

J=1

DO I=1,LEN(CHSTR)

IF (CHSTR(I:I).EQ.' ') THEN

ELSE

CHSTR(J:J) = CHSTR(I:I)

CHSTR(I:I) = ' '

J = J + 1

ENDIF

ENDDO

SHIFTBL = CHSTR

RETURN

END

0 Kudos
Steven_L_Intel1
Employee
1,105 Views
You don't show the call. However, I do know that the /gen-interface can't create an interface for a function returning CHARACTER(*) as that's not allowed in the language. This should not give an error, though - just a warning.

Functions returning CHARACTER*(*) are no longer standard Fortran and are considered bad practice, as the length depends on how you declare the function in the caller.
0 Kudos
Dishaw__Jim
Beginner
1,105 Views
Out of curiosity, what is the approved solution for returning a string. Lets consider a function that takes a string as an argument and will return the upper case version of it without modifying the original string (the input argument is INTENT(IN) and not INTENT(INOUT)).
0 Kudos
anthonyrichards
New Contributor III
1,105 Views

I always use

length=len_trim(string)
call sub(string,length)

Subroutine string (string,length)

integer length
character string(length)
...
...

and ALWAYS ensure thatI do not go beyond 'length'
when processing the string.

0 Kudos
Steven_L_Intel1
Employee
1,105 Views
In Fortran 90 you can do something like this:

function myfunc (arg) result (res)
character(len=*), intent(in) :: arg
character(len(arg)) :: res

This does require an explicit interface (putting it in a module will do it.)
0 Kudos
Reply