Skip to content

A runtime error occurs when assigning a variable of bitset_large #726

Closed
@degawa

Description

@degawa

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 main

The 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

2b7280b

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 build

Then install it in the bitset_test directory.

D:\stdlib>cmake --install build --prefix ../bitset_test
D:\stdlib>cd ..\bitset_test

In 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_stdlib

When 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_large

The 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 set1 from out to inout and use the automatic array allocation for the component blocks:
        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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions