2

I am looking at a Fortran function that returns an array (of pointers) to fixed length strings. Something like this:

FUNCTION F(N)
INTEGER :: N
CHARACTER(LEN=16) :: F(N)

F(1:N) = 'DEFAULT'
...
END FUNCTION F

The function computes N strings and to my understanding tries to return these strings in an array.

The caller has:

...
ALLOCATE(X(N))
X = F(N)

However I get a segfault when F returns. The author claims he does not see any issues when he compiles and runs it. I am trying to understand when the memory gets allocated for the actual strings and whether the memory is in scope after return? Does the

CHARACTER(LEN=16) :: F(N)

line allocate N*16 characters and then N pointers pointing to them in F? I am coming from C so maybe I am missing this completely, please be gentle. I suspected that the actual pointed to memory by F is not bound after the return (I thought that it could be on the stack etc.)

Any insight is appreciated.

0

1 Answer 1

1

Your function doesn't return an array of pointers, it returns an array of characters of length 16. You may be assigning the return value to a pointer or allocatable variable of a rank 1 array character(len=16), but that is a separate issue.

A function returning an array needs an explicit interface. It isn't clear from your question if this requirement has been met and this can be accomplished three ways:

  1. put the function in a module (easiest!)
  2. put the function in the main program after a contains statement
  3. write an interface block for the function in the scoping unit is used in.

For example:

module A
contains
  function f(n)
    implicit none
    integer :: n
    character(len=16) :: f(n)

    f(1:n) = 'DEFAULT'
  end function f
end module A

program test
  use A
  implicit none
  character(len=16), pointer :: array(:)

  allocate(array(10))
  array = f(10)

  print *, array
end program test

This puts your function within module 'A' as is with slight the addition of implicit none statement, which you should be using. Unlike C, Fortran will let you use variables without declaring them and implicitly assign types to them, which rears its ugly head when a typo creates a new variable and a debugging nightmare. implicit none tells the compiler to only use variables you declare.

The main program in the example above stores the return value of function in a pointer to a character array. The return value is not simply N*16 bytes because, unlike C, Fortran strings contain some metadata, including the length (and are not null terminated). The array itself will have an array descriptor internally that stores information on the array bounds, dimensions and some other information, so the overall allocation will be for at least N*(16+character scalar overhead)+array descriptor length. A bit more is going on under the hood than in C.

A last point to note, the variable f of the same name of the funtion f is the type of the function and its return value. This will be in scope when the function returns and the memory will be copied into the allocated memory of array. A final potential issue you might run into as a C programmer is that Fortran passes arguments by reference. This isn't an issue here, but later on this might crop up if you assumed pass by value like C does.

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for taking the time to comment! There is an interface defined indeed that I did not show. It is not clear to me is what is the purpose of ALLOCATE(X(N))? I thought that the array is allocated by the F function. I should have shown of course that X is declared as CHARACTER(LEN=16), ALLOCATABLE :: X(:)
Reallocation on assignment is only applicable when the left hand side is allocatable. Your example uses a pointer for the left hand side - reallocation on assignment will not apply, regardless of compiler options.
@IanH I took that bit out. I originally used an allocatable but changed to a pointer to match the Q but forgot to take out the reallocation stuff. thanks for pointing it out.
You guys are talking way over my head. I have no clue now... are you saying that the code should work? Valgrind complains about the call to F. I guess I will have to try to upgrade my compiler.
I upvoted the answer, mainly because it pointed me to the right direction. I realize that the answer can be not much better than the question... So I found something that helped: I changed ALLOCATABLE to POINTER and the code started working. Now I just need to understand better what happened here. It is still puzzling that the author claims that he compiled it with gfortran and ifort on different machines and never saw a segfault. Thanks guys!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.