- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Despite the debug window show errer in my last post https://community.intel.com/t5/Intel-Fortran-Compiler/ifort-debug-bug/td-p/1520195/jump-to/first-unread-message.
the contains subroutines exhibits very strange bugs. see the following simple program which has two contains subroutines, resize and resize2, the two subs are identical except the name.
The program will run in failure in the second call to resize2( windows 10, VS 2022 community, IFORT or IFX). However if you remove the contains sub resize which is never called, all are OK.
This bug is very difficult to debug. can anyone explain it? thanks.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
module mydata
type tlist
integer*4,allocatable::items(:)
character (len=:), allocatable :: name
contains
final:: free_tlist
endtype
type(tlist),dimension(:),allocatable,target:: a,b
contains
impure elemental subroutine free_tlist(object)
type (tlist), intent(inout) :: object
if(allocated(object%items))deallocate(object%items)
endsubroutine
endmodule
program main
use mydata
integer::i
call resize2()
call resize2()
contains
subroutine resize()
integer::newsize,osize,i
type(tlist),dimension(:),allocatable:: c
osize=0
if(allocated(b))osize=size(b)
newsize=osize+1
allocate(c(newsize))
do i=1,osize
c(i)=b(i)
enddo
call MOVE_ALLOC(c,b)
allocate(b(newsize)%items(20))
do i=1,20
b(newsize)%items(i)=i+20
enddo
endsubroutine
subroutine resize2() !same as sub resize
integer::newsize,osize,i
type(tlist),dimension(:),allocatable:: c
osize=0
if(allocated(b))osize=size(b)
newsize=osize+1
allocate(c(newsize))
do i=1,osize
c(i)=b(i)
enddo
call MOVE_ALLOC(c,b)
allocate(b(newsize)%items(20))
do i=1,20
b(newsize)%items(i)=i+20
enddo
endsubroutine
end program main
Prefer that you insert as shown so we can read it - and try and stay in the same lane.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, @Steve_Lionel , I deleted the other thread!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What version of Visual Studio are you using? There are known issues with v17.7.x. We are working on a solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I see the same issue (at least very similar) in my production code after upgrading from 2023.1 to 2023.2. VS version is 17.6.2.
The error message is the same (153 - "allocatable array or pointer is not allocated"). My code also implements a dynamically growing array. That array contains a custom type, which in turn contains another custom type (abstract) which is not being used/allocated in all cases. I tested with a case where this object is not being used and ran into the deallocation error. Then I removed that unused object from the type declaration and the problem disappeared! It does not make a difference if the growing array is using allocatables and move_alloc or pointers and simple (de)allocate.
I tried to reproduce this scenario in a smaller example, but didn´t succeed in that, so I cannot put my finger on exactly what makes the difference.
One thing I noticed is that when using pointer arrays and I right away deallocate the freshly allocated array again there is no error if I use the same pointer used for allocation, but the error does occur if I use another pointer assigned to the array, like so (much simplified):
type(myType), pointer :: tmp(:), arr(:)
allocate(tmp(5))
arr => tmp
deallocate(arr) ! fails
deallocate(tmp) ! works
Can you confirm the issue?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
module mydata
implicit none (type, external)
type tlist
integer, allocatable::items(:)
endtype
type(tlist),dimension(:),allocatable,target:: a,b
endmodule
program main
use mydata
implicit none (type, external)
call resize2() ! first call ok
call resize2() ! runtime crash in second call , if they are both resize1() it runs
! if we delete the uncalled resize1 it runs also
! finally I commented out the substance of resize1 and it still fails
contains
subroutine resize1()
! integer::newsize,osize,i
! type(tlist),dimension(:),allocatable:: c
! osize=0
! if(allocated(b))osize=size(b)
! newsize=osize+1
! allocate(c(newsize))
! do i=1,osize
! c(i) = b(i)
! enddo
! call MOVE_ALLOC(c,b)
! allocate(b(newsize)%items(20))
! do i=1,20
! b(newsize)%items(i)=i+20
! enddo
endsubroutine
subroutine resize2() !same as sub resize
integer::newsize,osize,i
type(tlist),dimension(:),allocatable:: c
osize=0
if(allocated(b))osize=size(b)
newsize=osize+1
allocate(c(1))
do i=1,osize
c(i) = b(i)
enddo
call MOVE_ALLOC(c,b) ! fails on this line
allocate(b(newsize)%items(20))
do i=1,20
b(newsize)%items(i)=i+20
enddo
endsubroutine
end program main
Out of interest I cut down the reproducer a bit. It seems the presence of a preceding contains routine is important, as even with zero code in the first subroutine the problem is encountered and if the running code is the first subroutine it works. It also works if we remove the module and put the declarations in main. I am guessing some namespace house keeping is at error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Andrew, isn´t it that in your version the second call to resize2 fails with array out of bounds in the second allocate statement (not deallocation triggered by move_alloc) because you only allocate c to size 1 instead of "newsize"?
To me it seems like only the first routine containing a move_alloc (or deallocate) statement for a given custom type will work as expected. If I just comment out this line of resize() (the first function):
call MOVE_ALLOC(c,b)
then I can call resize2() any number of times without problems. I also tried with my production code using pointer arrays, and it seems when I delegate all deallocate(myObjectArray) to a module function and not call any deallocate on that type in any other function I can get around the problem.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't think so, move_alloc(from, to) and from as allocated the size is not important at that point I think.
The bigger point is that the code runs or doesn't run based on any number of changes elsewhere in the code that should have no effect.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Andrew, my point was that in your code line 39 it is
allocate(c(1))
while in the original code it is
allocate(c(newsize))
so after move_alloc the size of b is always 1, and in the second call to the function when newsize is 2 and you access b(newsize) in line 44 then index 2 is out of bounds. This is at least how your version fails for me. If you really do get the original error (153 - "allocatable array or pointer is not allocated") when calling move_alloc I´d be curious how it can fail in different ways for you and me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK C was allocated newsize when I made the initial tests, I tried a few different things and posted the wrong version. But in all the tests that failed the debug exception was always on the move_alloc. If you look at the case below, it fails on the move alloc but if I comment out the never used mov_alloc in resize1 is does not fail. This is just indicative of the code incorrectly managing memory (corruption) so unrelated changes change the behaviour.
module mydata
implicit none (type, external)
type tlist
integer, allocatable::items(:)
endtype
type(tlist),dimension(:),allocatable,target:: a,b
endmodule
program main
use mydata
implicit none (type, external)
call resize2() ! first call ok
call resize2() ! runtime crash in second call , if they are both resize1() it runs
! if we delete the uncalled resize1 it runs also
! finally I commented out the substance of resize1 and it still fails
contains
subroutine resize1()
integer::newsize,osize,i
type(tlist),dimension(:),allocatable:: c
call MOVE_ALLOC(c,b) ! comment the never called line to 'fix' the code
endsubroutine
subroutine resize2() !originally the same as sub resize1
integer::newsize,osize,i
type(tlist),dimension(:),allocatable:: c
osize=0
if(allocated(b))osize=size(b)
newsize=osize+1
allocate(c(newsize))
do i=1,osize
c(i) = b(i)
enddo
call MOVE_ALLOC(c,b) ! fails on this line
allocate(b(newsize)%items(20))
do i=1,20
b(newsize)%items(i)=i+20
enddo
endsubroutine
end program main
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can reproduce the runtime crash with the 2023.2.0 version of ifx.
ifx -g -traceback -O0 old.f90
$ ./a.out
forrtl: severe (153): allocatable array or pointer is not allocated
Image PC Routine Line Source
a.out 0000000000405DEF resize2 32 old.f90
a.out 0000000000405211 main 13 old.f90
a.out 00000000004051CD Unknown Unknown Unknown
libc.so.6 00007F11A0566B4A Unknown Unknown Unknown
libc.so.6 00007F11A0566C0B __libc_start_main Unknown Unknown
a.out 00000000004050E5 Unknown Unknown Unknown
but I tested a pre-build of the upcoming 2024.0.0 and it's not present
ifx -g -traceback -O0 -what -V repro.f90
Intel(R) Fortran 24.0-1238.1
GNU ld version 2.39-9.fc38
$ ./a.out
$
I'm not sure what fixed this, but it's fixed and in the code for 2024.0.0. We're wrapping up last minute edits to the 2024.0.0 version. Due out in Q4 2023.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page