I found this code to behave unexpectedly
module testmodule
integer, parameter :: LCHARS = 50
contains
subroutine init()
call foobar("foobar")
end subroutine
subroutine foobar(s)
character(len=*), intent(in) :: s
call bar(s)
end subroutine
subroutine bar(str)
character(len=LCHARS), intent(in) :: str
print *, str
end subroutine
end module
program foo
use testmodule
call init()
end program
This code prints garbage which is compiler dependent.
I see the problem being the fact that I am jumping through a routine with len=*
for a string argument, which is then passed to a routine with specified length for the string argument.
What's going on exactly under the hood, and where in the standard is this behavior described? Should I refrain from having specified length for character routine arguments, since this behavior may happen at any time without warning?
Argument passing is compiler-dependent, as long as the requirements of the standard are fulfilled, but generally, a CHARACTER(len=*) dummy argument will have an interface something like
void foo(char *s, int len)
and in the implementation of the foo procedure the hidden len argument is used as the string length. OTOH, for a CHARACTER(len=somevalue) argument the hidden len argument is either ignored or not passed at all, and the code for the procedure assumes that somevalue is the correct length of the string.
As you have seen, you should never use anything but LEN=* unless you really know what you're doing and can quote chapter and verse from the standard to explain why.
I think your code is non-conforming. Section
12.4.1.1
of the Fortran 95 standard states:The problem is that
bar
requires a string of length 50 (cf.character(len=LCHARS), intent(in) :: str
), whereas the string you are passing it is only of length 6. Compiling this withproduces the error
As far as know all Fortran arguments are passed by reference. Behind the scenes, what the function
bar
gets is a pointer to the start of the stringstr
and an extra parameter whose value is the length of the string. Sobar
will take 50 characters worth of memory, starting at the beginning ofstr
, and print that to screen. Since the string that you pass is only 6 characters long, the remaining 44 characters will be whatever is in the next bit of memory after "foobar", which will differ at run time or depending on the compiler you use.