0

This is a follow-up question to the previous question

The difference here is that the optional argument is an array. Nevertheless, this is NOT a duplicate question as this question adds additional aspect such as different compiler behavior/failure when the optional argument is an array as opposed to a scalar.

main.F90

program main
  use my_module

  real(8) :: a
  real(8), allocatable, dimension(:,:) :: b

  a = 1.3 

  allocate(b(2,2))
  b(1,1)=1.0
  b(1,2)=2.0
  b(2,1)=3.0
  b(2,2)=4.0

  !call my_subroutine1(a, b)  ! case 1
  !call my_subroutine2(a, b)  ! case 2
  !call my_subroutine1(a)     ! case 3
  call my_subroutine2(a)     ! case 4

end program main

test.F90

module my_module
contains

  subroutine my_subroutine1(a, b)
    class(*), intent(in) :: a
    class(*), intent(in), optional, dimension(:,:) :: b

    select type (a) 
    type is (real(4))
      print*, 'real 4 a (my_subroutine1): ', a
    type is (real(8))
      print*, 'real 8 a (my_subroutine1): ', a
    end select

    if (present(b)) then
      print*, 'b is present in subroutine1'
      select type (b) 
      type is (real(4))
        print*, 'real 4 b: ', b
      type is (real(8))
        print*, 'real 8 b: ', b
      end select
    else
    end if

    call my_subroutine3(a, b)

  end subroutine my_subroutine1

  subroutine my_subroutine2(a, b)
    real(8), intent(in) :: a
    real(8), intent(in), optional, dimension(:,:) :: b

    print*, 'real 8 a (my_subroutine2): ', a
    if (present(b)) then
      print*, 'b is present in subroutine2'
      print*, 'real 8 b: ', b
    else
    end if

    call my_subroutine3(a, b)

  end subroutine my_subroutine2

  subroutine my_subroutine3(a, b)
    class(*), intent(in) :: a
    class(*), intent(in), optional, dimension(:,:) :: b

    select type (a) 
    type is (real(4))
      print*, 'real 4 a (my_subroutine3): ', a
    type is (real(8))
      print*, 'real 8 a (my_subroutine3): ', a
    end select

    if (present(b)) then
      print*, 'b is present in subroutine3'
      select type (b) 
      type is (real(4))
        print*, 'real 4 b: ', b
      type is (real(8))
        print*, 'real 8 b: ', b
      end select
    end if

  end subroutine my_subroutine3

end module my_module

The first 3 subroutine calls (cases 1, 2 and 3) in main.F90 behave as expected. However, when case 4 is called (call my_subroutine2(a)), segmentation fault occurs:

 real 8 a (my_subroutine2):    1.29999995231628     
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image              PC                Routine            Line        Source             
a.out              000000000040EB4A  Unknown               Unknown  Unknown
libpthread-2.17.s  00007F5358615630  Unknown               Unknown  Unknown
a.out              00000000004059F0  Unknown               Unknown  Unknown
a.out              00000000004084AA  Unknown               Unknown  Unknown
a.out              00000000004038A2  Unknown               Unknown  Unknown
libc-2.17.so       00007F535825A555  __libc_start_main     Unknown  Unknown
a.out              00000000004037A9  Unknown               Unknown  Unknown

Intel compiler versions 18.0.5.274, 19.0.5.281, 2020.2, and 2021.3.0 all failed. However, with Gnu/9.2.0, it behaves as expected:

 real 8 a (my_subroutine2):    1.2999999523162842     
 real 8 a (my_subroutine3):    1.2999999523162842  

So, I am thinking this is an Intel bug. NOW, comment out in main.F90 the allocation of b:

  !allocate(b(2,2))  
  !b(1,1)=1.0                                 
  !b(1,2)=2.0        
  !b(2,1)=3.0                                 
  !b(2,2)=4.0 

Even though b is not allocated, subroutines should not have a problem since b is an optional argument.

Gnu/9.2.0 now gives segfault for case 4:

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7f2c313863ff in ???
#1  0x7f2c320bd611 in get_float_string
    at /tmp/Role.Apps/spack-stage/spack-stage-gcc-9.2.0-wqdecm4rkyyhejagxwmnabt6lscgm45d/spack-src/libgfortran/io/write_float.def:1070
#2  0x7f2c320bfdd5 in list_formatted_write_scalar
    at /tmp/Role.Apps/spack-stage/spack-stage-gcc-9.2.0-wqdecm4rkyyhejagxwmnabt6lscgm45d/spack-src/libgfortran/io/write.c:1879
#3  0x7f2c320b3365 in wrap_scalar_transfer
    at /tmp/Role.Apps/spack-stage/spack-stage-gcc-9.2.0-wqdecm4rkyyhejagxwmnabt6lscgm45d/spack-src/libgfortran/io/transfer.c:2369
#4  0x7f2c320b3365 in wrap_scalar_transfer
    at /tmp/Role.Apps/spack-stage/spack-stage-gcc-9.2.0-wqdecm4rkyyhejagxwmnabt6lscgm45d/spack-src/libgfortran/io/transfer.c:2346
#5  0x40195b in __my_module_MOD_my_subroutine3
    at /scratch2/NCEPDEV/stmp1/Minsuk.Ji/Fortran/03/test.F90:62
#6  0x402142 in __my_module_MOD_my_subroutine2
    at /scratch2/NCEPDEV/stmp1/Minsuk.Ji/Fortran/03/test.F90:41
#7  0x40354f in MAIN__
    at /scratch2/NCEPDEV/stmp1/Minsuk.Ji/Fortran/03/main.F90:18
#8  0x40358f in main
    at /scratch2/NCEPDEV/stmp1/Minsuk.Ji/Fortran/03/main.F90:2
Segmentation fault

Even more confusingly, Intel's now give segfault for case 2 in addition to case 4.

minsuk ji
  • 23
  • 4
  • I submitted a very similar looking bug report to intel a few months back (concerning problems with `present()` and polymorphic arguments), which they assure me is going to be fixed in the next release. Your code looks fine to me. More bug reports can't hurt though. – veryreverie Nov 04 '21 at 14:28
  • Please explain why the array nature of the argument leads to a different answer from "test with latest release of the compiler(s) and report the bug to the compiler vendor(s)" (and be clear in asking a question here). Would it be a different question with rank-4 arrays, or a `real(4) b`, or a `class(mytype)` dummy? What are you expecting us, instead of the compiler vendors, to be able to say? – francescalus Nov 04 '21 at 15:03
  • In the previous question, a single Intel compiler version was found to be at fault and easily verified. Here, multiple Intel versions as well as Gnu are giving errors. Variations leading to the segfault are not as simple as, say, `real(4)` vs `real(8)`; for example, it involves if the actual argument is allocated or not allocated although it is never used in some cases. Do these not warrant more investigation/discussion? I wanted to see if 1) any one else has the same issue, 2) any one can shed light in terms of inner workings of Fortran. – minsuk ji Nov 04 '21 at 15:27
  • Neither "Do these not warrant more investigation/discussion?" nor "Does any one else has the same issue?" are very good questions for this format at Stack Overflow. This site is really for solving some answerable problems, not for open-ended discussions. You may have better success at a discussion Forum, such as https://fortran-lang.discourse.group/ – Vladimir F Героям слава Nov 04 '21 at 15:37
  • If you believe you have uncovered compiler bugs, it is best to report them to the compiler vendor. You can also ask a question if you are not sure if the behaviour is expected (a bug in your code) or not. But if you are reasonably sure your code is not at fault, you probably should ask something else. But some real answerable question. – Vladimir F Героям слава Nov 04 '21 at 15:39
  • I was hoping for someone to point out the 'correct way` to pass unlimited class optional array argument, and hopefully the reason for it. I didn't think I uncovered bugs spanning multiple compiler vendors and versions; one reason being the error triggers and responses are different. – minsuk ji Nov 04 '21 at 15:56
  • While the reference to previous question is fine (potentially helpful, even), it should not be necessary to read that question in order to understand this one. This post currently doesn't contain a question, only some observations about the behavior of compiled code. Additionally, I suspect the code could be reduced further (is the behavior the same after removing everything related to the required `a` parameter?). – outis Nov 05 '21 at 00:27

0 Answers0