Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29280 Discussions

Strange seg fault combining strings and optional integers

dgprendergast
Beginner
599 Views
This is truly weird. I'm using ifort 10.1 and have seen the same behavior with 9.1.
If I include a string and an optional integer as subroutine arguments, I get a seg fault if I *don't* include the integer in a call. Here's the example code:

==============================================
program main

integer :: i,j
character(5) :: s

s='dummy'
j=1

call sub( s, i, j )
print *, i

! seg fault will happen with this call
call sub( s, i )
print *,i

end program main

subroutine sub( s, i, j )
character(*) :: s
integer :: i
integer,optional :: j

i=0
if( present(j) ) i=j

end subroutine sub
==============================================

I've tried various combinations. The seg fault only seems to occur for character arguments. I tried integers and reals and it worked fine. Also, a single character, rather than a string, produces the same error. Declaring intent(in) doesn't help either.

Any ideas? Is this a compiler problem?
Am I doing something that isn't standard f90?

David
0 Kudos
4 Replies
Steven_L_Intel1
Employee
599 Views
Is this a compiler problem? No. Are you doing something that isn't standard f90? Yes. A call to a procedure with an OPTIONAL argument requires that an explicit interface be visible to the caller. As you have written it, the compiler has no idea that j is optional and therefore does not pass the information about the omitted argument (an address of zero). The called routine then picks up a memory location that is not part of the passed argument list, with unpredictable results.

The best way to solve the problem is to make sub a CONTAINed routine or put it in a module. This will provide the explicit interface needed. If you don't want to do that but would like the compiler to diagnose such errors, add the options:

-gen-interface -warn interface

This is not foolproof - in part as it depends on order of compilation - but it would pick up this case if both main and sub were in the same file or if sub were compiled first.

For further reading, see Doctor Fortran and the Virtues of Omission and Doctor Fortran Gets Explicit!
0 Kudos
dgprendergast
Beginner
599 Views
Great response! Exactly what I wanted to know.
I understand now why I have modules which have such optional arguments that don't lead to errors. I wouldn't have realized that an explicit interface was necessary in the case above.
I guess I was confused that the same example worked without explicit interface for other data types.
Thanks for your help.

0 Kudos
Steven_L_Intel1
Employee
599 Views
You were just lucky that it seemed to work at all. The subroutine was picking up garbage from the stack.
0 Kudos
joseph-krahn
New Contributor I
599 Views
dgprendergast:
Great response! Exactly what I wanted to know.
I understand now why I have modules which have such optional arguments that don't lead to errors. I wouldn't have realized that an explicit interface was necessary in the case above.
I guess I was confused that the same example worked without explicit interface for other data types.
Thanks for your help.


With luck, it is possible for this to work without an explicit interface, if all arguments are pass-by-address, the optional arguments come last, and there are no string arguments. Even then, any reference to the missing optional arg is likely to segfault. If it happnes to point to a valid address, then the string version will still segfault because it passes the string length by value.

If you don't want to use modules, you can also define an explicit interface using the INTERFACE syntax. However, the standards are not very well designed for using INTERFACEs because they strongly favor using modules. So, it is really only useful when you want to add a few explicit interfaces to existing non-module code.
0 Kudos
Reply