8

I'm trying to learn Fortran2018 using gfortran. When playing around with pointers I noticed that there doesn't seem to be a facility to test for nullpointers. So I have two questions:

  1. Is there really no (straightforward) way to test if a pointer is a nullpointer or "ready to use" in Fortran?
  2. If there isn't, why wasn't it considered necessary in Fortran so far?

More practically speaking, in the code snippet below: How could we find out at any point during execution if assigning to p was "safe" or not? (Possibly imagining a more complex sequence of allocate, nullify, and deallocate statements.)

program test
      implicit none
      real, pointer :: p

      ! p = 333.333 ! Segfault, p is neither defined, nor allocated
      ! Since p is not defined, checking whether it's 
      ! associated to a target gives arbitrary results:
      print *, "Start: Pointer p associated? ", associated(p) ! Result: True or False

      nullify(p) ! Now p is defined, but `null`
      print *, "Nullyfied: Pointer p associated? ", associated(p) ! False
      ! p = 123.456 ! Still a segfault

      allocate(p) ! Now p can be accessed
      print *, "Allocated: Pointer p associated? ", associated(p) ! True
      p = 987.654 ! Now assignment is possible
      
      allocate(p) ! Loses the value pointed to by p.
      print *, p ! Result: 0.00000000

      deallocate(p) ! Now accessing p generates a segfault again.
      print *, "Deallocated: Pointer p associated? ", associated(p) ! False

      ! Never allowed:
      ! allocated(p)
      ! p == null()
      ! p .eqv. null()

      end program test
2
  • IMO the real point is that you wouldn't use a pointer, that's not the Fortran way. Use an allocatable, with which you can do all you are asking - Second rule of Modern Fortran: "Don't use pointers unless you really have to" Commented May 6, 2022 at 11:38
  • And to make explicit @IanBush's comment, unlike pointers, with allocatables it's always (since the broken Fortran 90 was superseded) possible to tell whether an allocatable object is safe to use. Commented May 6, 2022 at 11:47

2 Answers 2

9

In general, there is no safe way to tell whether a pointer is "ready to use", just as there is no safe way to tell whether a variable is currently defined.

The ASSOCIATED intrinsic function may be used only when the pointer is of defined association status, but there is no comparable way to determine (within the Fortran program itself) whether the pointer is of defined association status.

If the pointer is of defined association status, ASSOCIATED will tell you whether or not the pointer points to something (and can even be used in some cases whether it points to a particular thing) and can be used.

However, if the pointer is not of defined pointer association, an attempt to query its association status is a violation of the Fortran standard (this is stronger than the result being undefined, it means your entire program is broken).

You can help yourself by taking reasonable steps to ensure that the pointer association status does not become, or start as, undefined, but it's entirely your responsibility as a programmer to know whether or not the association status is defined.

One way to help is by setting the initial association status of your pointers:

real, pointer :: p => NULL()  ! Defined association status, not-associated
real, pointer :: q            ! Undefined association status

print *, ASSOCIATED(p)   ! Allowed
print *, ASSOCIATED(q)   ! Not allowed 

end

(I won't say that ASSOCIATED(p) tells us .FALSE., because that ASSOCIATED(q) means we don't have a valid program.)

To conclude, if you're careful you can use ASSOCIATED reliably to tell whether a pointer is associated, but you must be careful.

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

6 Comments

Thank you for the great answer. I didn't know that using associated() on an undefined pointer violates the standard. If indeed this is the case, I don't understand why the compiler "lets me get away with it". I get a warning form gfortran only if I use -Wall. I tried to compile your example with ifort and couldn't get any warning at all from it.
You "get away with it" because the compiler is generally under no obligation to see whether you have violated the standard. In this case, it's allowed to assume that you've given a standard-conforming program, rather than being required to test the pointer association definition status and diagnose for you.
How unfortunate :) Anyway, thanks again for the explanation. So I assume that if you put allocate(q) before the print statements in your code example it still wouldn't make the program actually "valid"? Because I noticed, that after calling allocate() on q, I could print its value (0) no problem, even if q wasn't "nullyfied" before that.
An allocate(q) would suffice: the allocation makes the association status defined (and indeed makes the pointer associated). But with pointers there are two bits of "defined" to consider: association status, and definition. After the allocate(q), it's pointer associated, but you still haven't defined its value: allocate(q); if (associated(q)) print*, q) is invalid, but because of the printing, not querying the association status.
@shitpoet, explicit initialization such as I give with p here will indeed give the data objects the SAVE attribute, but all the variables in the question and my answer already have the SAVE attribute because they are variables in main programs. For local variables that wouldn't otherwise be SAVEd and where SAVE would be a problem, then, yes, explicit initialization would have to be avoided and more care is required. But being careful is always necessary anyway, because initialization doesn't stop association status becoming undefined.
|
5

One tests for null pointers using the associated() function. It returns true for associated pointers and false for null pointers.

For undefined pointers the result is "undefined behaviour" (one can get anything).

1 Comment

Thanks for this very concise answer. It seems I mixed up null pointers with undefined pointers and you made it clear that they're actually not the same.

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.