Take the 2-minute tour ×

I have a FORTRAN code with a routine:

integer ncid, recid
character*(*) varname
real*8 vardata
dimension vardata(15,45,75)


I want to add some flexibility to this code, and I thought I would do it by first adding an optional flag argument:


! everything the same and then ...
logical, optional :: how_to_calculate

Now, at this point, I am not even using "how_to_calculate". I am just putting it into the code for testing. So I compile the code without a hitch. Then I run it, and I get an error in the subroutine. Specifically, some of the values in the code later on are "magically" altered from what they were without that optional argument. The new values don't make sense to the logic of the code, so it exits politely with an error message. Let me stress again that at this point, I am not even using this optional argument. So then, on a lark, I go back to all the places in the source that call this routine and, even though my new argument in optional, I put in values for it in all the calls. When I do that, the code runs fine. So, what's up? How can the mere presence of an unused optional argument in a subroutine result in other data being corrupted? And how can adding input parameters for this optional argument fix things again? This is being compiled with PGI, by the way.

Any ideas? Thanks.

BTW, sorry for not providing more code. My boss might not be too happy with me if I did that. I don't make the rules; I just work here.

share|improve this question
Do you reference how_to_calculate anywhere in READ_NC_VALS? –  Hristo Iliev Jul 10 '12 at 9:06
add comment

2 Answers

up vote 2 down vote accepted

Optional arguments in Fortran are implemented by passing 0 (a null pointer) for each optional argument that has no value provided by the calling subroutine. Because of this subroutines that take optional arguments have to:

  • either have an explicit INTERFACE definition inside the calling subroutine
  • or be a module-level subroutine (for them interfaces are generated automatically)

If you add an optional argument to a subroutine but it neither has an interface in the caller or is not a module-level subroutine, then the compiler will not generate the right calling sequence - it will pass less arguments than expected. This could pose a problem on Unix systems, where PGI passes the length of all CHARACTER*(*) arguments at the end of the argument list (on Windows it passes the length as the next argument after the address of the string). One missing argument would shift the length arguments placement in the stack (or put them in the wrong registers on x64) leading to the incorrect length of the VARNAME string being received by READ_NC_VALS. This could lead to all sorts of ill behaviour, including overwritting memory and "magically" changing values that should not change according to the program logic.

share|improve this answer
Thanks Hristo and eriktous. Could you provide a reference on this? I have looked at two books and several web pages, and this was never discussed. Thanks again. –  bob.sacamento Jul 10 '12 at 16:24
The necessity of having interfaces comes from the Fortran 90 strandard § The actual implementation of optional arguments is an implementation detail and hence is not covered by the standard. My reference is the assembly code produced by pgf90 -S, ifort -S and gfortran -S for several test cases. The statement about string length arguments comes from the PGI Workstation 6.0 manual (and also from the assembly code). –  Hristo Iliev Jul 10 '12 at 16:52
add comment

Obviously, just adding a dummy argument to a subroutine, with or without the optional attribute, shouldn't cause any problems. What might happen, though, is that the change exposes some other problem with the code, which was already there, but didn't cause any visible bad effects.

Without any more code, all we can do is guess, which usually isn't really useful. One thing that pops into mind is the necessity of an explicit interface, when using optional arguments. Is the code organized into modules?

share|improve this answer
This is old code I am editing here. A few modules have been incorporated over the years, but ninety some per cent of it is "module free." A major reorg of the code isn't possible without getting some permissions from people who don't want to give it. --sigh-- –  bob.sacamento Jul 9 '12 at 23:52
If the subroutine is not in a module, you'll have to use another way to provide an explicit interface. You can write an interface block, and include that everywhere the subroutine is referenced. It's error-prone, because you have to update it whenever you make a change to the subroutine. –  eriktous Jul 10 '12 at 12:39
add comment

Your Answer


