- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello everyone!
I have encountered the following problem with the move_alloc intrinsic:
I am expecting the following code
program strange
type :: Something
integer :: data
end type Something
class(Something), allocatable :: a, b
a = Something(100)
call move_alloc(from=a, to=b)
a = Something(200)
print *, a%data, b%data
end program strange
to output '200 100' (which it does with gfortran/pgfortran), but both ifort and ifx crash with the message:
forrtl: severe (122): invalid attempt to assign into a pointer that is not associated
Image PC Routine Line Source
a.out 00000000004085E6 Unknown Unknown Unknown
a.out 0000000000404B2A Unknown Unknown Unknown
a.out 0000000000404862 Unknown Unknown Unknown
libc.so.6 00007F65C86ACFD0 Unknown Unknown Unknown
libc.so.6 00007F65C86AD07D __libc_start_main Unknown Unknown
a.out 0000000000404765 Unknown Unknown Unknown
I am running Ubuntu 22.10 with ifort version 2021.4.0 and ifx version 2021.4.0 Beta.
Replacement of 'class' with 'type' does not cause the crash.
Regards, Oleg
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the nice reproducer and for the triage tip about changing Class to Type.
I filed a bug report, CMPLRIL0-34514, on your behalf.
In case you are interested, the failure occurs at the
a = Something(200)
statement. We added an ALLOCATED() check after the MOVE_ALLOC. A is not allocated. A should be allocated automatically since it is on the LHS (left hand side) and it is allocatable.
I'll let you know when it is fixed.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well that seems like a bug but your usage case seems very strange, in effect you are allocating B as the same size and bounds as A and afterwards A will be deallocated and B will be allocated but uninitialized. The intended usage of MOVE_ALLOC is to make and existing data structure bigger with only one data copy being needed. If you use STAT or ERRMSG what do you get?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Andrew!
'move_alloc' finishes without any error (stat==0).
Crash happens on assignment to the allocatable variable, which was 'from' argument of 'move_alloc' (line 11 of the listing above).
Looks like the internal state of that variable was not completely reset to the deallocated state.
My intended usage of 'move_alloc' is the following (pipeline of stream):
type, abstract :: tOutputStream
! ...
end type :: tOutputStream
type, extends(tOutputStream) :: tUnitOutputStream
! ...
end type tUnitOutputStream
type, extends(tOutputStream) :: tBase64OutputStream
class(tOutputStream), allocatable, private :: InnerStream
! ...
end type tBase64OutputStream
interface tBase64OutputStream
module procedure MakeBase64OutputStream
end interface tBase64OutputStream
function MakeBase64OutputStream(innerStream, ...) result(stream)
class(tOutputStream), intent(inout), allocatable :: innerStream
! ...
type(tBase64OutputStream) :: stream
call move_alloc(from=innerStream, to=stream%InnerStream)
! ...
end function MakeBase64OutputStream
type, extends(tOutputStream) :: tZLibOutputStream
class(tOutputStream), allocatable, private :: InnerStream
! ...
end type tZLibOutputStream
interface tZLibOutputStream
module procedure MakeZLibOutputStream
end interface tZLibOutputStream
function MakeZLibOutputStream(innerStream, ...) result(stream)
class(tOutputStream), intent(inout), allocatable :: innerStream
! ...
type(tZLibOutputStream) :: stream
call move_alloc(from=innerStream, to=stream%InnerStream)
! ...
end function MakeZLibOutputStream
! ...
stream = tUnitOutputStream(unit)
if (binary) then
stream = tBase64OutputStream(stream)
if (compressed) then
stream = tZLibOutputStream(stream)
end if
end if
Of course, the code above can be rewritten with pointers, but in my opinion, with allocatables it looks much cleaner (resembles the 'std::unique_ptr' from C++). Please correct me if I am doing something wrong/not in a Fortran-ish way. Thanks!
Regards, Oleg
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
stream%InnerStream = innerStream ! stream%InnerStream will be allocated AND get a copy of InnerStream data
deallocate( InnerStream )
Is this what you are trying to do? By default in Fortran on whole array assignment the LHS is automatically allocated or reallocated.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Technically, yes. But I am assuming that with 'move_alloc' the innerStream is transferred to stream%InnerStream without copying.
Then, e.g., on line:
stream = tBase64OutputStream(stream)
I assume that the 'stream' is moved inside the newly create instance of 'tBase64OutputStream' (and the 'stream' variable is in the 'deallocated' state), which is moved back into the 'stream'. And this line crashes with ifort.
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK I understand your usage, I think that is a compiler bug. Maybe some others will comment.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the nice reproducer and for the triage tip about changing Class to Type.
I filed a bug report, CMPLRIL0-34514, on your behalf.
In case you are interested, the failure occurs at the
a = Something(200)
statement. We added an ALLOCATED() check after the MOVE_ALLOC. A is not allocated. A should be allocated automatically since it is on the LHS (left hand side) and it is allocatable.
I'll let you know when it is fixed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This runtime failure is fixed in the current version of ifort, 2021.7.0. It was released last week as part of oneAPI 2022.3.
Please give it a try!
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page