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

Error passing string to subroutine

DavidWhite
Valued Contributor II
754 Views

Strange behaviour which I have only observed since installing XE2017 update 1, but don't know how long this has been happening.

        I = LEN_TRIM(logtext)
        CALL WriteScrollLine(browse_log,logtext(1:I))

I reports 22

logtext contains "Case No.   1 loaded 80" (variable length actually 80)

Subroutine WriteScrollLine(box, text)

IMPLICIT NONE

INTEGER, INTENT(IN) :: box
CHARACTER (LEN=*), INTENT(IN) :: text

text is now blank with length 0.

This does not happen on all calls.  Most calls to the subroutine run as expected.

Any ideas?

Thanks

David

0 Kudos
13 Replies
mecej4
Honored Contributor III
754 Views

text is now blank with length 0.

How did you see this?

If in the debugger, and your code was compiled with some level of optimization in effect, you may need to single-step  (F11) a couple of times before the locals and arguments displays are updated.

If not, please provide complete code for a test case. 

0 Kudos
jimdempseyatthecove
Honored Contributor III
754 Views

In addition to what mecej4 said, if the optimization inlined the subroutine, then the debugger may not show valid information for the variables.

If you are using other means to observe the incorrect results (log file has wrong data, diagnostic PRINT *,LEN(text), text), then this would be indicative of a compiler bug. As a potential work around, what happens if compile the callers without inter-file IPO. IOW force the subroutine out of line. Note NOINLINE may not have the same effect.

Jim Dempsey

0 Kudos
DavidWhite
Valued Contributor II
754 Views

The error is observed both in the debugger and in the behaviour of the program.  When calling the subroutine, some calls are printing blank lines when logtext contains 22 characters in the calling program.

My workaround at present is to remove the two faulty subroutine calls and place the write statements in the calling program.

Jim, as per your last paragraph, my interpretation is that this is a compiler bug in 17.1

I'll try your other suggestions as well.

David

0 Kudos
DavidWhite
Valued Contributor II
754 Views

Jim,

IPO is already turned off, as is inline function expansion.

David

0 Kudos
mecej4
Honored Contributor III
754 Views

What you may be seeing may be just the visible symptom of something else going wrong in your program. Often, exceeding array bounds may go undetected because the effects may be harmless. For example, given the declaration DIMENSION xx(10), yy(5), assigning a value to xx(13) may clobber yy(3), but if yy() gets initialized later before being used or output, you will see no harmful effects. If these variables are in different subroutines, a change in compiler options or updating to a newer version of the compiler can cause errors of the type that you encountered.

There may well be a new bug in Ifort 17.0.1; however, your example is not sufficient to establish that the bug exists.

0 Kudos
DavidWhite
Valued Contributor II
754 Views

Mea culpa!

Both calling routines had an obsolete INTERFACE block with an extra optional argument, which is no longer included in the called subroutine code.

Thanks,

David

0 Kudos
mecej4
Honored Contributor III
754 Views

The /warn:interfaces option would have caught that error.

0 Kudos
andrew_4619
Honored Contributor II
754 Views

If you have external routines and separate interfaces then submodules would be the way to go then it also becomes self checking irrespective of compiler options.

0 Kudos
jimdempseyatthecove
Honored Contributor III
754 Views

David,

        I = LEN_TRIM(logtext)
        CALL WriteScrollLine(browse_log,logtext(1:I))
        WRITE(*,*) LEN_TRIM(logtext), logtext ! use LEN_TRIM, not I

IOW does logtext get corrupted through the call? If so, then something else is going on.

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
754 Views

>>Both calling routines had an obsolete INTERFACE block with an extra optional argument, which is no longer included in the called subroutine code.

The calling routines shall not use an interface that does not properly describe that uses by the called routine. The missing optional argument may have the side effect of repositioning the hidden string lengths for character(*) (optional) arguments.

Try updating your interface (or rewriting the called routine to include the argument not used as stated in the interface).

Jim Dempsey

0 Kudos
DavidWhite
Valued Contributor II
754 Views

Jim,

The issue was that some calling routines had the INTERFACE block and some did not.  I changed the definition of the subroutine, eliminating what had previously been an optional argument, and thereby making the INTERFACE block inconsistent with the subroutine.  

The calls which came from the routines without the INTERFACE block worked (I may have seen an interface warning mecej4, but the local code looked OK).  The calls with the INTERFACE block were the ones which failed because of this programmer's error.

Having removed the optional argument, I now don't need to use INTERFACE.

David

0 Kudos
Steven_L_Intel1
Employee
754 Views

I will comment that it's not good form to have INTERFACE blocks for Fortran routines in your own application. I understand that sometimes this makes sense when updating an old application, but it is error-prone, as you found out. Better to use modules.

0 Kudos
DavidWhite
Valued Contributor II
754 Views

Thanks, Steve.

All the best for the next stage of life beyond Intel.

Thanks,

David

0 Kudos
Reply