Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28963 Discussions

Appending an array with object gives unexpected results

minhdao
Beginner
863 Views

I've used this syntax to append arrays and it has given me unexpected results in some cases using Intel compilers (both ifx and ifort on both Ubuntu and macOS runners, not so using gfortran and nvfortran):

array = [array, obj]

 I could reproduce it with ifort 2021.1 Beta 20201112 on a macOS runner (13.6.4) in the GitHub CI using this code:

module my_module
  implicit none
  private

  type, public :: my_type_set
    type(my_type), allocatable :: objects(:)
  contains
    procedure :: set_objects
  end type

  type, public :: my_type
    character(:), allocatable :: string
  end type

contains

  subroutine set_objects(set)
    class(my_type_set), intent(out) :: set

    type(my_type) :: obj_1, obj_2

    obj_1%string = 'one'
    obj_2%string = 'two'

    allocate (set%objects(0))
    set%objects = [set%objects, obj_1]
    set%objects = [set%objects, obj_2]
  end
end

program my_program
  use my_module, only: my_type_set, my_type
  implicit none

  type(my_type_set) :: set_of_objects

  call set_of_objects%set_objects()

  if (set_of_objects%objects(2)%string /= 'two') stop 1 ! Correct, does not stop
  if (set_of_objects%objects(1)%string /= 'one') stop 1 ! Empty string, stops
end

 

Labels (1)
0 Kudos
5 Replies
Barbara_P_Intel
Employee
808 Views

Can you please try the latest release of ifx or ifort? I cannot reproduce what you report using ifx 2024.0.0 or ifort 2021.11.0 on Linux.

The Intel Fortran compilers are no longer available for macOS. They were deprecated about a year ago and discontinued with the 2024.0 releases.

 

0 Kudos
minhdao
Beginner
734 Views

Ok, I appended a slightly longer code example that reproduces the error on Ubuntu 22.04.4 LTS using both ifx (IFX) 2024.0.2 20231213 and ifort (IFORT) 2021.10.0 20230609. The example is a little bit more complex, but if I boiled it down even further, the error somehow goes away on a Linux machine (even if I just remove the allocatable fields within version_t). However, it's quite clear that the error appears during the array extension step. Please pay attention to lines 77 to 79.

module version_f
  implicit none
  private

  public :: try_satisfy

  type :: string_t
    character(:), allocatable :: str
  end type

  type :: version_t
    integer :: major
    integer :: minor
    integer :: patch
    type(string_t), allocatable :: prerelease(:)
    type(string_t), allocatable :: build(:)
  end type

  type :: comparator_t
    character(:), allocatable :: op
    type(version_t) :: version
  end type

  type :: comparator_set_t
    type(comparator_t), allocatable :: comps(:)
  contains
    procedure, private :: parse_comp_set
  end type

  type :: version_range_t
    type(comparator_set_t), allocatable :: comp_sets(:)
  contains
    procedure, private :: parse_version_range
  end type

contains

  subroutine try_satisfy()
    type(version_range_t) :: version_range

    call version_range%parse_version_range()

    if (version_range%comp_sets(1)%comps(1)%op /= '>') then
      print *, 'Operator not >: ', version_range%comp_sets(1)%comps(1)%op; stop 1
    end if
  end

  subroutine parse_version_range(this)
    class(version_range_t), intent(out) :: this

    type(comparator_set_t) :: comp_set

    allocate (this%comp_sets(0))

    call comp_set%parse_comp_set()

    this%comp_sets = [this%comp_sets, comp_set]
  end

  subroutine parse_comp_set(this)
    class(comparator_set_t), intent(out) :: this

    type(comparator_t) :: comp

    allocate (this%comps(0))

    comp%op = '>'
    comp%version%major = 1
    comp%version%minor = 0
    comp%version%patch = 1
    this%comps = [this%comps, comp]

    comp%op = '<'
    comp%version%major = 2
    comp%version%minor = 1
    comp%version%patch = 0
    print *, 'before array extension: ', this%comps(1)%op ! Prints '>'
    this%comps = [this%comps, comp]
    print *, 'after array extension: ', this%comps(1)%op ! Prints '0'
  end
end


program test
  use version_f
  implicit none

  call try_satisfy()
end program

 

0 Kudos
ChrisC1
Beginner
711 Views

Works on a Linux but fails on Windows, is a flag that this may be a stack overflow issue.   Windows defaults to a ~1MB and Linux is around 8MB if I recall correctly.   The compiler may be doing a temp array on the stack to extend the array in your program.   Might try setting increasing the exe stack size using  /STACK linker flag.  

0 Kudos
Barbara_P_Intel
Employee
682 Views

@minhdao, what output do you expect for a successful execution?

With ifx 2024.0.2 I get

$ a.out
 before array extension: >
 after array extension: 0
 Operator not >: 0
1

However, with a preview version of 2024.1.0, I get

$ a.out
 before array extension: >
 after array extension: >

If the preview 2024.1.0 is correct, that is planned to be available in the next month or so.

The reproducer runs the same on Windows.

 

0 Kudos
minhdao
Beginner
679 Views

That's interesting @Barbara_P_Intel. Yes, the preview 2024.1.0 gives the expected result. Looking forward to trying it out with the new release.

0 Kudos
Reply