Error passing string to subroutine

Error passing string to subroutine

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

14 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Quote:

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. 

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

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

Jim,

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

David

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.

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

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

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.

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

>>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

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

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.

Retired 12/31/2016

Thanks, Steve.

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

Thanks,

David

Leave a Comment

Please sign in to add a comment. Not a member? Join today