- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You were just lucky that it seemed to work at all. The subroutine was picking up garbage from the stack.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page