Deallocate pointer in fortran [duplicate] - pointers

My IDE is Code::Blocks 17.2 with compiler GFortran 6.3.1
The all code is:
PROGRAM EES_TEST
USE , NON_INTRINSIC :: DERIVED_TYPE
IMPLICIT NONE
INTEGER :: I , ALLOC_ERR , DEALLOC_ERR
LOGICAL :: GLOBAL_ERR
CLASS ( TRONA ) , POINTER :: P_TRA
TYPE ( TRONA ) , ALLOCATABLE , TARGET :: TRAN(:)
IF ( .NOT. ALLOCATED ( TRAN ) ) ALLOCATE ( TRAN ( 2 ) , STAT = ALLOC_ERR )
IF ( ALLOC_ERR .NE. 0 ) STOP ("PROBLEM WITH MEMORY ALLOCATION - TRAN!!!")
OPEN ( UNIT = 15 , FILE = 'INPUT.TXT' , ACTION = 'READ' )
DO I = 1 , 2
P_TRA => TRAN ( I )
GLOBAL_ERR = P_TRA%UCI()
IF ( GLOBAL_ERR .EQV. .TRUE. ) STOP ("ERROR WITH READING FROM OUTPUT.TXT!")
END DO
CLOSE ( 15 )
IF ( ALLOCATED ( TRAN ) ) DEALLOCATE ( TRAN , STAT = DEALLOC_ERR )
IF ( DEALLOC_ERR .NE. 0 ) STOP ("PROBLEM WITH MEMORY DEALLOCATION - TRAN!!!")
END PROGRAM EES_TEST
MODULE DERIVED_TYPE
IMPLICIT NONE
TYPE , PUBLIC :: TRONA
PRIVATE
REAL :: Sn
REAL :: Vn
CONTAINS
PROCEDURE , PUBLIC :: UCI => UCI_POD_TRONA
PROCEDURE , PUBLIC :: TAKE_Sn => TAKE_POD_Sn
PROCEDURE , PUBLIC :: TAKE_Vn => TAKE_POD_Vn
END TYPE TRONA
PRIVATE :: UCI_POD_TRONA
PRIVATE :: TAKE_POD_Sn , TAKE_POD_Vn
CONTAINS
FUNCTION UCI_POD_TRONA ( THIS ) RESULT ( WRONG )
IMPLICIT NONE
CLASS ( TRONA ) :: THIS
LOGICAL :: WRONG
WRONG = .FALSE.
READ ( 15 , * , ERR = 100 ) THIS%Sn
READ ( 15 , * , ERR = 101 ) THIS%Vn
RETURN
100 WRITE (*,*) "WRONG FORMAT - INPUT 100!"
WRONG = .TRUE.
STOP
101 WRITE (*,*) "WRONG FORMAT - INPUT 101!"
WRONG = .TRUE.
STOP
END FUNCTION UCI_POD_TRONA
FUNCTION TAKE_POD_Sn ( THIS ) RESULT ( POD_Sn )
IMPLICIT NONE
CLASS ( TRONA ) :: THIS
REAL :: POD_Sn
POD_Sn = THIS%Sn
RETURN
END FUNCTION TAKE_POD_Sn
FUNCTION TAKE_POD_Vn ( THIS ) RESULT ( POD_Vn )
IMPLICIT NONE
CLASS ( TRONA ) :: THIS
REAL :: POD_Vn
POD_Vn = THIS%Vn
RETURN
END FUNCTION TAKE_POD_Vn
END MODULE DERIVED_TYPE
I am very new in object oriented programing in Fortran so I need an explanation about using the object pointer for calling methods from derived types. In this case I want to check is there any problem with memory leaking and if it is case is there method for checking how much memory was lost and in which line? Another thing is nullifying the derived type pointer. How to do that for this case?

Generally, unless you allocate something somewhere, you cannot have memory leaks. It is simply impossible. You can only leak something you allocate as a pointer target, nothing else.
In your code you have no allocate() for a pointer, so there cannot be any memory leaks.
For a memory leak to happen, two things must happen in sequence.
An anonymous pointer target must be allocated. That is possible only through the allocate statement
allocate(p_tra)
The pointer to the target is lost. Either it is redirected somewhere else
p_tra => somewhere_else
Or it ceases to exist, because it is a local variable of a subroutine that finishes or it is a component of a structure which is deallocated or similar...
You can always use GCC sanitizations -fssnitize=leak or valgrind to check for memory leaks.
Regarding the nulifying, just use the nulify statement or assign to null(). It is a pointer like any other.
p_tra => null()

Related

Why could NOT the pointer-chain be allocated continously in Fortran-90? [duplicate]

This question already has an answer here:
Associated pointers in derived type? gFortran vs. Intel
(1 answer)
Closed 3 years ago.
I'm trying to learn the data-strcuture of a linked-list using Pointers in Fortran 90 on the platform of Win32/x86.
But when I runs the test-case that simply aims to build a list of 100 items, the program terminates with and error of 'Access violation'.
And the list is far from finished before the error occurs.
In debug run, it turns out that, at some point, the allocation of NEXT-Pointer fails.
I'm wondering why could this happen?
How could the linked-list be build successfully using pointers?
Codes are as follows:
TYPE Ptr
INTEGER :: I
TYPE(Ptr),POINTER :: PREV,NEXT
END TYPE Ptr
TYPE(Ptr),POINTER :: P
INTEGER :: IP,Err
ALLOCATE(P)
DO IP=1,100
P%I = IP
IF ( .NOT.ASSOCIATED(P%NEXT) ) THEN
ALLOCATE(P%NEXT, STAT=Err )
END IF
P%NEXT%PREV => P
P => P%NEXT
END DO
On UBUNTU with gfortran 7.2 your program compiled and ran just fine. There are, however two issues with your program, that may trip off your compiler:
After you allocate p the status of the pointers p%next and p%prev is undefined. It might be that your compiler then gets tripped on the statement IF(.not.associated(p%next)), as the status of p%next is undefined. Always nullify pointers before you use them or refer to them in any which way. Try:
program pointers
!
TYPE Ptr
INTEGER :: I
TYPE(Ptr),POINTER :: PREV,NEXT
END TYPE Ptr
!
TYPE(Ptr),POINTER :: P => NULL() ! Make sure all pointer are nullified
TYPE(Ptr),POINTER :: head => NULL()
TYPE(Ptr),POINTER :: temp => NULL()
INTEGER :: IP,Err
!
NULLIFY(P) ! This is identical to the nullify in the declaration statement
NULLIFY(head) ! I've added it to show both styles
NULLIFY(temp)
!
ALLOCATE(P)
NULLIFY(P%NEXT) ! Always nullify pointers
NULLIFY(P%PREV) ! Always nullify pointers
head => P ! To keep a header to your list is a good idea
!
DO IP=1,100
write(*,*) ip
P%I = IP*IP ! Trivial unimportant change
!
IF ( .NOT.ASSOCIATED(P%NEXT) ) THEN
ALLOCATE(P%NEXT, STAT=Err )
P%NEXT%I = ip+1 ! define entries
NULLIFY(P%NEXT%NEXT) ! for next node
NULLIFY(P%NEXT%PREV) ! for all elements of your TYPE
END IF
!
P%NEXT%PREV => P
P => P%NEXT
!
END DO
!
temp => head ! temporary pointer to navigate
DO WHILE( ASSOCIATED(temp) )
write(*,*) ' AT NODE ', temp%i
temp => temp%next
ENDDO
!
end program pointers
As pointed out by #Alexander Vogt, you loose the start of the list. I added a pointer called head to retain this beginning of the list. If you look at the output you will notice that the program actually makes a list of 100+1 entries, since you make p first, then you add 100 times a p%next.

MPI: send and recv must share the same communicator. Why?

I have found written
"A message can ONLY be received within the same communicator from which it was sent".
However, if I look at this picture
https://imgur.com/a/hYz4dWd
and then analyze this code
Send and Receive operations between communicators in MPI
use mpi !instead of include 'mpif.h'
implicit none
integer :: tag,ierr,rank,numtasks,color,new_comm,inter1,inter2
integer :: sendbuf,recvbuf,stat(MPI_STATUS_SIZE)
integer :: irank
!
tag = 22
sendbuf = 222
!
call MPI_Init(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,numtasks,ierr)
!
if (rank < 2) then
color = 0
else
color = 1
end if
!
call MPI_COMM_SPLIT(MPI_COMM_WORLD,color,rank,new_comm,ierr)
!
if (color .eq. 0) then
call MPI_INTERCOMM_CREATE(new_comm,0,MPI_Comm_world,2,tag,inter1,ierr)
!
call MPI_COMM_RANK(inter1,irank,ierr)
if(irank==0)then
call mpi_send(sendbuf,1,MPI_INT,0,tag,inter1,ierr)
end if
!
else if(color .eq. 1) then
call MPI_INTERCOMM_CREATE(new_comm,0,MPI_COMM_WORLD,0,tag,inter2,ierr)
call MPI_COMM_RANK(inter2,irank,ierr)
if(irank==0)then
call mpi_recv(recvbuf,1,MPI_INT,0,tag,inter2,stat,ierr)
if(ierr/=MPI_SUCCESS)print*,'Error in rec '
print*,'rec buff = ', recvbuf
end if
end if
!
call MPI_finalize(ierr)
end program h
to me it seems that I am communicating between two different communicators: inter1 and inter2. Turning to the picture attached, I am communicating from comm1 towards comm2.
The picture is unrelated to the sample code.
Looking at the code, one rank MPI_Send(..., inter1, ...) and an other MPI_Recv(..., inter2, ...).
What matters here is how inter1 and inter2 were created, and they both come from all the ranks invoking MPI_Intercomm_create(), so even if you use different variable names, they indeed refer to the same (and unique) inter-communicator.
Here is a more intuitive way the program could have been written
use mpi !instead of include 'mpif.h'
implicit none
integer :: tag,ierr,rank,numtasks,color,new_comm,inter,remote_leader
integer :: sendbuf,recvbuf,stat(MPI_STATUS_SIZE)
integer :: irank
!
tag = 22
sendbuf = 222
!
call MPI_Init(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,numtasks,ierr)
!
if (rank < 2) then
color = 0
remote_leader=2
else
color = 1
remote_leader=0
end if
!
call MPI_COMM_SPLIT(MPI_COMM_WORLD,color,rank,new_comm,ierr)
!
call MPI_INTERCOMM_CREATE(new_comm,0,MPI_Comm_world,remote_leader,tag,inter,ierr)
call MPI_COMM_RANK(inter,irank,ierr)
if (irank.eq.0) then
if(color.eq.0) then
call mpi_send(sendbuf,1,MPI_INT,0,tag,inter,ierr)
else if(color.eq.1) then
call mpi_recv(recvbuf,1,MPI_INT,0,tag,inter,stat,ierr)
if(ierr/=MPI_SUCCESS)print*,'Error in rec '
print*,'rec buff = ', recvbuf
end if
end if
!
call MPI_finalize(ierr)
end program

Odd behavior of fortran strings in a derived type after accessing the type by a pointer

[Working example at the end of this post!]
I'm trying to write a simple module to handle physical units in arithmetic operations. My aim is to create derived units out of primary ones.
As you can see in the following code, I have a derived type, namely unit_t, which stores a string, representing the unit itself, power of the unit, conversion factor (to convert it to SI), a logical variable to show if the unit is cloned and next and prev pointers which point to the next or previous unit (in case we have a combination of units, for example kg * m / s**2, so basically it's a linked list connecting different units to each other).
I have a function named unit_clone to clone a primary unit. The unit_int_pow function overloads the exponentiation operator (**) and it simply clones a given primary unit and updates its exponent. The units_mul function overloads the multiplication operator (*). This function first check if the two given units are cloned (if not, it clones them) and then just connect them using next and prev pointers.
Here is my code (you should be able to compile it with gfortran)
module units
implicit none
type unit_t
character(len=16) :: symb
integer :: pow
real :: conv
logical :: cloned
type(unit_t), pointer :: next => null(), prev => null()
end type unit_t
! definitions
type(unit_t), target :: m = unit_t("m", 1, 1.d0, .false.)
type(unit_t), target :: km = unit_t("km", 1, 1.d3, .false.)
type(unit_t), target :: kg = unit_t("kg", 1, 1.d0, .false.)
type(unit_t), target :: s = unit_t("s", 1, 1.d0, .false.)
interface operator (**)
procedure unit_int_pow
end interface operator (**)
interface operator (*)
procedure units_mul
end interface operator (*)
contains
!> Cloning a given node (unit)
function unit_clone(u) result (clone)
implicit none
type(unit_t), intent(in) :: u
type(unit_t), allocatable, target :: clone
allocate(clone)
clone%symb = u%symb
clone%conv = u%conv
clone%pow = u%pow
clone%cloned = .true.
clone%next => u%next
clone%prev => u%prev
end function unit_clone
!> integer powers
function unit_int_pow(u1, p) result(u)
implicit none
type(unit_t), intent(in) :: u1
integer, intent(in) :: p
type(unit_t), allocatable, target :: u
u = unit_clone(u1)
u%pow = u%pow * p
end function unit_int_pow
!> multiplication
function units_mul (u1, u2) result (u1c)
implicit none
type(unit_t), intent(in) :: u1, u2
type(unit_t), allocatable, target :: u1c, u2c
if ( u1%cloned ) then
u1c = u1
else
u1c = unit_clone(u1)
end if
if ( u2%cloned ) then
u2c = u2
else
u2c = unit_clone(u2)
end if
u2c%prev => u1c
u1c%next => u2c
end function units_mul
end module units
program test
use units
implicit none
type(unit_t) :: u
u = kg**2 * m
print *, u%symb, "^", u%pow, " [expected: kg^2]"
print *, u%next%symb, "^", u%next%pow, " [expected: m^1]"
print *, u%next%prev%symb, "^", u%next%prev%pow, " [expected: kg^2]"
end program test
The problem is, I'm getting the following output:
kg ^ 2 [expected: kg^2]
�ȷ2�U ^ 1 [expected: m^1]
�ȷ2�U ^ 2 [expected: kg^2]
Apparently, after accessing the next or next%prev unit (which is basically the head of this short linked list), the code outputs random character instead of the symbs. If I change the order of the variables in the derived type, unit_t, for example if I put symb at the end of the derived type, I will get right symbs, but this time wrong pows.
Any idea what is the culprit of this rather odd behavior?
Using Rudrigo's comment below, I rewrote the code, and it works fine now. Just for the reference, the working code is as follows (if you have further suggestion or modification, please let me know, Nombre respository)
module units
implicit none
type unit_t
character(len=16) :: symb
real :: conv
real :: pow = 1.d0
logical :: cloned = .false.
type(unit_t), pointer :: next => null(), prev => null()
end type unit_t
! units definitions
type(unit_t), target :: m = unit_t("m", 1.d0)
type(unit_t), target :: km = unit_t("km", 1.d3)
type(unit_t), target :: kg = unit_t("kg", 1.d0)
type(unit_t), target :: s = unit_t("s", 1.d0)
interface operator (**)
procedure unit_int_pow
end interface operator (**)
interface operator (*)
procedure units_mul
end interface operator (*)
contains
!> Cloning a given node (unit)
function unit_clone(u) result (clone)
implicit none
type(unit_t), intent(in) :: u
type(unit_t), pointer :: clone
allocate(clone)
clone%symb = trim(u%symb)
clone%conv = u%conv
clone%pow = u%pow
clone%cloned = .true.
clone%next => u%next
clone%prev => u%prev
end function unit_clone
!> integer powers
function unit_int_pow(u1, p) result(u)
implicit none
type(unit_t), intent(in) :: u1
integer, intent(in) :: p
type(unit_t), pointer :: u
if ( u1%cloned ) then
! TODO: should be able to handle complex cases like: a * (b * c)**3
! most likly, only updating the power of the linked list chain
! would do the job
else
u => unit_clone(u1)
end if
u%pow = u%pow * p
end function unit_int_pow
!> multiplication
function units_mul (u1, u2) result (u2c)
implicit none
type(unit_t), intent(in), target :: u1, u2
type(unit_t), pointer :: u2c
if ( u2%cloned ) then
if ( associated(u2%prev) ) then
u2c => u2%prev%next
else
u2c => u2
end if
else
u2c => unit_clone(u2)
end if
if ( u1%cloned ) then
if ( associated(u2%prev) ) then
u2c%prev => u1%prev%next
else
u2c%prev => u1
end if
else
u2c%prev => unit_clone(u1)
end if
u2c%prev%next => u2c
end function units_mul
end module units
A pointer in Fortran has three posible association status:
associated: the pointer is actually pointing to a defined and allocated variable / matching data storage (its target);
disassociated: it was (or is part of an objects that was) explicitly nullified or deallocated, or its target was properly disassociated.
undefined: anything different than the former, e.g. its target is (or became) undefined, or was deallocated by other means than by calling deallocate directly in the pointer itself, among other causes.
When execution of an instance of a subprogram completes (e.g. when function units_mul reaches end function), any unsaved local variable becomes undefined. Also, any allocatable local variable that is not saved or is a function result gets deallocated, and when an allocatable entity is deallocated, it also becomes undefined.
Back to your problem, u2c is an allocatable unsaved local variable inside units_mul function, where you associate u1c%next to it. When this function reaches the end, u2c ends its lifecycle and becomes undefined, bringing u1c%next to become also undefined, in a state referred in the Fortran lingo as dangling pointer.
This a text from the Fortran Standard describing this phenomena (even though it is referring to the case of modules host association, it's the same logic):
Note 19.10
A pointer from a module program unit might be accessible in a
subprogram via use association. Such pointers have a lifetime that is
greater than targets that are declared in the subprogram, unless such
targets are saved. Therefore, if such a pointer is associated with a
local target, there is the possibility that when a procedure defined
by the subprogram completes execution, the target will cease to exist,
leaving the pointer “dangling”. This document considers such pointers
to have an undefined association status. They are neither associated
nor disassociated. They cannot be used again in the program until
their status has been reestablished. A processor is not required to
detect when a pointer target ceases to exist.
A dangling pointer is not a reliable pointer, and the compiler has no control over it. They may, by any reason, keep pointing to their last memory address (and accidentally give the expected result in some cases, or the values would be gibberish from random memory address), but it will most certainly break, and the fail can be anything, from just wrong results to a SIGSEG fault or a memory address violation.
See this example code:
program dangling_pointer
implicit none
integer, pointer :: p(:)
integer, allocatable :: a(:)
call sub1(p)
print *, 'sub1: ', p
call sub2(p)
print *, 'sub2: ', p
call sub3(p, a)
print *, 'sub3: ', p
p => fun4()
print *, 'fun4: ', p
contains
subroutine sub1(dummy_p)
! the pointer passed as argument outlives the local target
! when the procedure ends, it becomes a "dangling pointer"
integer, pointer :: dummy_p(:)
integer, allocatable, target :: local_a(:)
allocate(local_a(5))
local_a = 100
dummy_p => local_a
end
subroutine sub2(dummy_p)
! here the local variable is saved, so it persists. No problem here.
integer, pointer :: dummy_p(:)
integer, allocatable, target, save :: saved_a(:)
allocate(saved_a(5))
saved_a = 100
dummy_p => saved_a
end
subroutine sub3(dummy_p, out_a)
! here the target is a passed argument, so it persists. No problem here.
integer, pointer :: dummy_p(:)
integer, allocatable, target :: out_a(:)
allocate(out_a(5))
out_a = 100
dummy_p => out_a
end
function fun4() result(result_p)
! here the function result will be returned as a pointer. No problem here.
integer, pointer :: result_p(:)
allocate(result_p(5))
result_p = 100
end
end
With gfortran 9.0.0 I get:
sub1: 14316208 0 14287184 0 100
sub2: 100 100 100 100 100
sub3: 100 100 100 100 100
fun4: 100 100 100 100 100
Edit
I think this snippet would work for your problem:
allocate(u1c%next)
if (u2%cloned) then
u1c%next = u2
else
u1c%next = unit_clone(u2)
end if
u1c%next%prev => u1c

Fortran interoperability with C pointer struct

I have a commercial C library which I want to use with Fortran. There are two functions and a pointer struct like:
struct env;
typedef struct env *ENVptr;
the two functions have the prototype:
ENVptr open(int *status_p);
int close(ENVptr **env_p);
I wrote an Fortran interface to access them:
interface
function c_open(status) bind(c, name='c_open')
use, intrinsic :: iso_c_binding
integer(kind = c_int) :: status
type(c_ptr) :: c_open
end function
function c_close(env) bind(c, name='c_close')
use, intrinsic :: iso_c_binding
type(c_ptr) :: env
integer(kind = c_int) :: c_close
end function
end interface
I use this code to use this in my Fortran program:
type(c_ptr) :: env = c_null_ptr
env = c_open(status)
if ( status .ne. 0 ) then
print *, 'Could not open environment'
stop
end if
...some more code...
if ( c_associated(env) ) then
status = c_close(env)
if ( status .ne. 0 ) then
print *, 'Could not close environment.'
end if
end if
but when I execute the program, I get an Segmentation fault error when the program reaches the c_close function.
Is this the right way to interface the C routines?
I don't see how your program could have linked because the binding name of a procedure has to agree with the name in the actual C prototype. I suppose you could square the names up with a *.def file. Also Fortran has a concept of argument keywords so it is good practice in my opinion to make the Fortran dummy arguments in the interface agree with their documented argument names. Other than that you seem to have the right level of indirection in your interface bodies, so my version would be:
interface
function c_open(status_p) bind(C,name='open')
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr) :: c_open
integer(kind = c_int) status_p
end function c_open
function c_close(env_p) bind(c,name='close')
use, intrinsic :: iso_c_binding
implicit none
integer(c_int) c_close
type(c_ptr) env_p
end function c_close
end interface
Now, there is a problem with the level of indirection when you invoke c_close because the C typedef for ENVptr already makes it a pointer, so ENVptr** envp is a pointer to a pointer to a pointer. In your Fortran code you are passing a c_ptr that points at an opaque type by reference, so you are passing a pointer to a pointer. Thus you need to create an extra level of indirection to make it fly. I would accordingly attempt to modify your code to something like:
type(c_ptr) :: env = c_null_ptr, envpp = c_null_ptr
target env
integer(c_int) status
env = c_open(status)
if ( status .ne. 0 ) then
print *, 'Could not open environment'
stop
end if
!...some more code...
if ( c_associated(env) ) then
envpp = c_loc(env)
status = c_close(envpp)
if ( status .ne. 0 ) then
print *, 'Could not close environment.'
end if
end if
I can't test this obviously but at this point it's syntactically correct and has the right level of indirection according to my reading of your problem statement.

Using a derived type pointer and a polymorphic target in Fortran

The Fortran function listed below compiles and executes as expected using ifort 11.1. However GFortran 4.6 returns the compiler error:
THIS_NML => THIS
Error: Different types in pointer assignment at (1); attempted assignment of CLASS(UNIT) to TYPE(UNIT).
Fortran code:
FUNCTION PROCESS_COMMAND(THIS, CMD, DATA) RESULT(RET)
CLASS(UNIT), INTENT(INOUT), TARGET :: THIS
CHARACTER(LEN = *), INTENT(IN) :: CMD
CHARACTER(LEN = *), INTENT(IN) :: DATA
CHARACTER(LEN = 200) :: STRING
INTEGER :: IOS
TYPE(UNIT), POINTER :: THIS_NML
! CREATE A NAMELIST
NAMELIST /VARS/ THIS_NML
THIS_NML => THIS
RET = 0
STRING = '&VARS THIS_NML%' // TRIM(CMD) // ' = ' // TRIM(DATA) // ' /'
! READ CMD AND DATA
READ(STRING, NML=VARS, IOSTAT=IOS)
RET = IOS
END FUNCTION PROCESS_COMMAND
Because namelist's cannot be created using polymorphic objects, the derived type pointer THIS_NML is being used to create the namelist. Any ideas how to make this work with GFortran?
Try using select type construct. Something like
select type ( A => THIS )
type is ( UNIT )
Here you can treat A as nonpolymorphic variable of type UNIT (if the test is succesful).
end select

Resources