Relating to this Program does not return from`deallocate` statement discussion, I wrote a custom allocator (I use this word though it is just a debug layer on top of normal Fortran allocation) since I guess I have some deep memory issues.
Basically I want to track base addresses (and related size) of entities being allocated (to try to see if at some point there is some memory overlapping, resulting in corruption).
Here is the full file code:
module Allocation
implicit none
private
public :: delete, alloc, setAllocOutUnit
logical :: is_unit_set = .false.
integer :: iunit = 9999
interface delete
! module procedure delete_
module procedure deleteI
module procedure deleteR
end interface
interface alloc
module procedure allocI0_
module procedure allocR0_
module procedure allocDP0_
module procedure allocI_
module procedure allocR_
end interface
contains
subroutine setAllocOutUnit(iun)
integer, intent(in) :: iun
iunit = iun
is_unit_set = .true.
end subroutine setAllocOutUnit
subroutine printFileAndLine_(file, line)
character(len = *), intent(in), optional :: file
integer, intent(in), optional :: line
! character(len = 32) :: fmt = ' '
character(len = 64) :: buf = ' '
integer :: ilen
if (.not. present(file)) return
! write(unit=fmt, fmt='(a)') '( " @", a )'
write(unit=buf, fmt='( " @", a )') file
if (present(line)) then
ilen = len_trim(buf)
ilen = ilen + 1
write(unit=buf(ilen:), fmt='( "(", i0, ")" )') line
endif
ilen = len_trim(buf)
ilen = ilen + 1
write(unit=buf(ilen:), fmt='(a)') ':'
write(iunit, '(a)', advance='no') buf(1 : len_trim(buf) + 2)
end subroutine printFileAndLine_
subroutine varIsAllocatedMsg_(name)
character(len = *), intent(in) :: name
write(iunit, '(3a)') &
'variable "', name, '" is already allocated at this point in time.'
end subroutine varIsAllocatedMsg_
subroutine varIsDeallocatedMsg_(name)
character(len = *), intent(in) :: name
write(iunit, '(3a)') &
'variable "', name, '" is already de-allocated at this point in time.'
end subroutine varIsDeallocatedMsg_
subroutine printDims_(dims)
integer, intent(in) :: dims(..)
integer :: ndims, i
select rank (dims)
rank(0)
write(iunit, fmt='(a, i0)') &
'Dimensions: ', dims
rank (1)
ndims = size(dims)
write(iunit, fmt='(a)', advance='no') 'Dimensions: '
do i = 1, ndims - 1
write(iunit, fmt='(i0, " - ")', advance='no') dims(i)
enddo
write(iunit, fmt='(i0)') dims(ndims)
end select
end subroutine printDims_
subroutine allocOKMsg_(name, iloc, nbytes)
character(len = *), intent(in) :: name
integer(kind = 8), intent(in) :: iloc, nbytes
write(iunit, fmt='(2a, 2(a, i0), ". ")', advance='no') &
'variable "', name, '" allocated. Location in memory: ', iloc, &
'. Occupancy (bytes): ', nbytes
end subroutine allocOKMsg_
subroutine allocKOMsg_(name, istat, emsg)
character(len = *), intent(in) :: name, emsg
integer, intent(in) :: istat
write(iunit, fmt='(3a)') &
'[ERROR] variable "', name, '" could not be allocated.'
write(iunit, fmt='(15x, a, i0, 2a)') &
'Exit code ', istat, '. Error message: ', emsg(1 : len_trim(emsg))
end subroutine allocKOMsg_
subroutine deallocOKMsg_(name)
character(len = *), intent(in) :: name
write(iunit, fmt='(3a)') &
'variable "', name, '" correctly de-allocated.'
end subroutine deallocOKMsg_
subroutine deallocKOMsg_(name, istat, emsg)
character(len = *), intent(in) :: name, emsg
integer, intent(in) :: istat
write(iunit, fmt='(3a)') &
'[ERROR] variable "', name, '" could not be de-allocated.'
write(iunit, fmt='(15x, a, i0, 2a)') &
'Exit code ', istat, '. Error message: ', emsg(1 : len_trim(emsg))
end subroutine deallocKOMsg_
subroutine wrongDimsRankMsg_()
write(*, fmt='(5x, "--", a)') &
'[ERROR] When allocating NDrank array, dimensions must be passed as 0D/1D-rank array.'
write(iunit, fmt='(a)') &
'[ERROR] When allocating NDrank array, dimensions must be passed as 0D/1D-rank array.'
end subroutine wrongDimsRankMsg_
subroutine dimsMismatchMsg_(irank, ndims)
integer, intent(in) :: irank, ndims
write(iunit, fmt='( a, 2(i0, a) )') &
'[ERROR] Rank and number of dimensions do not match! (', &
irank, ' vs. ', ndims, ')'
end subroutine dimsMismatchMsg_
subroutine allocI0_(var, name, file, line)
integer, allocatable :: var
character(len = *), intent(in) :: name
character(len = *), intent(in), optional :: file
integer, intent(in), optional :: line
integer :: istat
character(len = 256) :: emsg
call printFileAndLine_(file, line)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
return
else
allocate(var, stat = istat, errmsg=emsg)
endif
if (istat == 0) then
call allocOKMsg_(name, loc(var), sizeof(var))
write(iunit, *) ''
else
call allocKOMsg_(name, istat, emsg)
endif
end subroutine allocI0_
subroutine allocR0_(var, name, file, line)
real, allocatable :: var
character(len = *), intent(in) :: name
character(len = *), intent(in), optional :: file
integer, intent(in), optional :: line
integer :: istat
character(len = 256) :: emsg
call printFileAndLine_(file, line)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
return
else
allocate(var, stat = istat, errmsg=emsg)
endif
if (istat == 0) then
call allocOKMsg_(name, loc(var), sizeof(var))
else
call allocKOMsg_(name, istat, emsg)
endif
end subroutine allocR0_
subroutine allocDP0_(var, name, file, line)
double precision, allocatable :: var
character(len = *), intent(in) :: name
character(len = *), intent(in), optional :: file
integer, intent(in), optional :: line
integer :: istat
character(len = 256) :: emsg
call printFileAndLine_(file, line)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
return
else
allocate(var, stat = istat, errmsg=emsg)
endif
if (istat == 0) then
call allocOKMsg_(name, loc(var), sizeof(var))
else
call allocKOMsg_(name, istat, emsg)
endif
end subroutine allocDP0_
subroutine allocI_(var, name, dims, file, line)
integer, allocatable :: var(..)
integer, intent(in) :: dims(..)
character(len = *), intent(in) :: name
character(len = *), intent(in), optional :: file
integer, intent(in), optional :: line
integer :: ndims, irank, istat
character(len = 256) :: emsg
integer :: dim_
call printFileAndLine_(file, line)
select rank (dims)
rank (0)
dim_ = dims
select rank (var)
rank (1)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
else
allocate(var(dim_), stat=istat, errmsg=emsg)
endif
rank default
irank = rank(var)
call dimsMismatchMsg_(irank, 1)
error stop
end select
rank (1)
ndims = size(dims)
select rank (var)
rank (1)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
else
if (ndims == 1) then
allocate(var(dims(1)), stat=istat, errmsg=emsg)
else
call dimsMismatchMsg_(1, ndims)
error stop
endif
endif
rank (2)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
else
if (ndims == 2) then
allocate(var(dims(1), dims(2)), &
stat=istat, errmsg=emsg)
else
call dimsMismatchMsg_(2, ndims)
error stop
endif
endif
rank (3)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
else
if (ndims == 3) then
allocate(var(dims(1), dims(2), dims(3)), &
stat=istat, errmsg=emsg)
else
call dimsMismatchMsg_(3, ndims)
error stop
endif
endif
end select
rank default
call wrongDimsRankMsg_()
error stop
end select
if (istat == 0) then
call allocOKMsg_(name, loc(var), sizeof(var))
call printDims_(dims)
else
call allocKOMsg_(name, istat, emsg)
endif
end subroutine allocI_
subroutine allocR_(var, name, dims, file, line)
real, allocatable :: var(..)
integer, intent(in) :: dims(..)
character(len = *), intent(in) :: name
character(len = *), intent(in), optional :: file
integer, intent(in), optional :: line
integer :: ndims, irank, istat
character(len = 256) :: emsg
integer :: dim_
! NOTE: this is a copy from allocI_
! Changes only declaration-type of var.
call printFileAndLine_(file, line)
select rank (dims)
rank (0)
dim_ = dims
select rank (var)
rank (1)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
else
allocate(var(dim_), stat=istat, errmsg=emsg)
endif
rank default
irank = rank(var)
call dimsMismatchMsg_(irank, 1)
error stop
end select
rank (1)
ndims = size(dims)
select rank (var)
rank (1)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
else
if (ndims == 1) then
allocate(var(dims(1)), stat=istat, errmsg=emsg)
else
call dimsMismatchMsg_(1, ndims)
error stop
endif
endif
rank (2)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
else
if (ndims == 2) then
allocate(var(dims(1), dims(2)), &
stat=istat, errmsg=emsg)
else
call dimsMismatchMsg_(2, ndims)
error stop
endif
endif
rank (3)
if (allocated(var)) then
call varIsAllocatedMsg_(name)
else
if (ndims == 3) then
allocate(var(dims(1), dims(2), dims(3)), &
stat=istat, errmsg=emsg)
else
call dimsMismatchMsg_(3, ndims)
error stop
endif
endif
end select
rank default
call wrongDimsRankMsg_()
error stop
end select
if (istat == 0) then
call allocOKMsg_(name, loc(var), sizeof(var))
call printDims_(dims)
else
call allocKOMsg_(name, istat, emsg)
endif
end subroutine allocR_
! subroutine delete_(var, name, file, line)
! type(*), allocatable :: var(..)
! character(len = *), intent(in) :: name
! character(len = *), intent(in), optional :: file, line
! integer :: istat
! character(len = 256) :: emsg
! call printFileAndLine_(file, line)
! if (allocated(var)) then
! deallocate(var, stat=istat, errmsg=emsg)
! if (istat == 0) then
! call deallocOKMsg_(name)
! else
! call deallocKOMsg_(name, istat, emsg)
! endif
! else
! call varIsDeallocatedMsg_(name)
! endif
! end subroutine delete_
subroutine deleteI( var, name, file, line )
implicit none
integer, allocatable :: var(..)
character( len = * ), intent(in) :: name
character( len= * ), optional, intent(in) :: file
integer, optional, intent(in) :: line
integer :: ist
character(len = 256) :: emsg
call printFileAndLine_(file, line)
if (allocated(var)) then
deallocate( var, stat=ist, errmsg=emsg)
if (ist == 0) then
call deallocOKMsg_(name)
else
call deallocKOMsg_(name, ist, emsg)
endif
else
call varIsDeallocatedMsg_(name)
endif
end subroutine deleteI
subroutine deleteR(var, name, file, line)
implicit none
real, allocatable :: var(..)
character( len = * ), intent(in) :: name
character( len= * ), optional, intent(in) :: file
integer, optional, intent(in) :: line
integer :: ist
character(len = 256) :: emsg
call printFileAndLine_(file, line)
if (allocated(var)) then
deallocate( var, stat=ist, errmsg=emsg)
if (ist == 0) then
call deallocOKMsg_(name)
else
call deallocKOMsg_(name, ist, emsg)
endif
else
call varIsDeallocatedMsg_(name)
endif
end subroutine deleteR
end module Allocation
In allocI_()
, at line
call allocOKMsg_(name, loc(var), sizeof(var))
the compiler (ifort: Version 2021.7.1 Build 20221019_000000
) generates:
allocator.f90(355): catastrophic error: **Internal compiler error: internal abort** Please report this error along with the circumstances in which it occurred in a Software Problem Report. Note: File and line given may not be explicit cause of this error.
Intel Documentation states " If it is an assumed-rank array, it must not be associated with an assumed-size array
", which it should not be.
Is the code wrong, or could it be a compiler bug?
Thanks.