- Notifications
You must be signed in to change notification settings - Fork 197
Description
Description
A runtime error occurs when assigning bitset_large type variables to oneself. Such a situation arises when extending stdlib_sorting to support sorting arrays of bitset_large type. The error message is Fortran runtime error: Allocatable argument 'set2' is not allocated. set2 is defined in the procedure assign_large as the variable on the right-hand side of the assignment operator.
This phenomenon can be reproduced with the following code.
program main use, intrinsic :: iso_fortran_env use :: stdlib_bitsets implicit none type(bitset_large) :: bitsetl(0:16**3 - 1) integer(int32) :: i character(32) :: bin do i = 0, size(bitsetl, kind=int32) - 1 write (bin, '(b32.32)') i call bitsetl(i)%from_string(bin) end do bitsetl(0) = bitsetl(0) end program mainThe details are described in the Additional Information section. For simplicity, gfortran 11.2.0 was used as the compiler, and -Wall -Wextra -Wimplicit-interface -fPIC -g -fcheck=all -fbacktrace was used as the compile option. The options are specified in the actions defined in ci_windows.yml.
Expected Behaviour
I expected the bitsetl(0) value to remain unchanged in the above code.
Version of stdlib
Platform and Architecture
Windows 10 22H2 64bit, gfortran 11.2 bundled with quickstart Fortran on Windows
Additional Information
Here I describe how I identified the issue.
The directory structure was
D:\ ├─bitset_test └─stdlib Cloned stdlib and built it with compiler options used in the actions defined in ci_windows.yml.
D:\>git clone https://github.com/fortran-lang/stdlib.git D:\>cd stdlib D:\stdlib>cmake -Wdev -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_Fortran_FLAGS_DEBUG="-Wall -Wextra -Wimplicit-interface -fPIC -g -fcheck=all -fbacktrace" -DCMAKE_MAXIMUM_RANK:String=4 -DCMAKE_Fortran_COMPILER=gfortran -G "Unix Makefiles" D:\stdlib>cmake --build buildThen install it in the bitset_test directory.
D:\stdlib>cmake --install build --prefix ../bitset_test D:\stdlib>cd ..\bitset_testIn the bitset_test directory, I compiled main.f90 using gfortran. The main.f90 is shown the Description section.
>gfortran main.f90 -Wall -Wextra -Wimplicit-interface -fPIC -g -fcheck=all -fbacktrace -Iinclude\fortran_stdlib\GNU-11.2.0 -Llib -lfortran_stdlibWhen running the generated executable file a.exe, a runtime error occurred, and the error message was displayed:
D:\bitset_test>a At line 97 of file D:/stdlib/build/src/stdlib_bitsets_large.f90 Fortran runtime error: Allocatable argument 'set2' is not allocated Error termination. Backtrace: Could not print backtrace: libbacktrace could not find executable to open ...The line specified by the message is in the procedure assign_large that performs the assignment operation of bitset_large type.
pure module subroutine assign_large( set1, set2 ) ! Used to define assignment for bitset_large type(bitset_large), intent(out) :: set1 type(bitset_large), intent(in) :: set2 set1 % num_bits = set2 % num_bits allocate( set1 % blocks( size( set2 % blocks, kind=bits_kind ) ) ) set1 % blocks(:) = set2 % blocks(:) end subroutine assign_largeThe error may be due to the deallocation of the component blocks of set2 caused by the intent(out) attribute for set1 since set1 and set2 are the same variable.
I changed the attribute of set1, the argument specifying the left-hand side of the assignment operator, from out to inout and re-run the executable again, followed by the above procedures. An error still occurred, but the message has changed to Attempting to allocate already allocated variable 'set1'.
D:\bitset_test>a At line 97 of file D:/stdlib/build/src/stdlib_bitsets_large.f90 Fortran runtime error: Attempting to allocate already allocated variable 'set1' Error termination. Backtrace: Could not print backtrace: libbacktrace could not find executable to open ...Since the same variables are specified on both sides of the assignment operator, it is natural that the variable on the left side is already allocated. But no error should occur in this situation.
The solutions I am trying to are:
- change the intent of
set1fromouttoinoutand use the automatic array allocation for the componentblocks:
set1 % num_bits = set2 % num_bits - allocate( set1 % blocks( size( set2 % blocks, kind=bits_kind ) ) ) - set1 % blocks(:) = set2 % blocks(:) + set1 % blocks = set2 % blocks(:)- Or eliminate the user-defined assignment procedure and use Fortran's intrinsic assignment operation of use-defined type.