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

an access violation i can't understand when using function <transfer>

Li_L_
New Contributor I
679 Views
program main
implicit none
integer(4),parameter::  lp = 4_4, ip = 4_4
integer(4)::            i,j

    i = 52793874
    j = i
    print*, anyiseq(i,j)
    print*, anyiseq2(i,j)

contains

    !--compare two scalar byte by byte
    elemental logical(lp) function anyiseq(lhs,rhs) result(r)
    class(*),intent(in)::               lhs,rhs
    integer(1),dimension(sizeof(lhs)):: lb
    integer(1),dimension(sizeof(rhs)):: rb
    integer(ip)::                       i
        r   = .false.
        if(.not.same_type_as(lhs,rhs))  return
        if(.not.size(lb)==size(rb))     return
        lb  = transfer(lhs,mold=lb)
        rb  = transfer(rhs,mold=rb)
        r   = all(lb==rb)
    end function anyiseq
    
    !--compare two scalar byte by byte
    logical(lp) function anyiseq2(lhs,rhs) result(r)
    class(*),intent(in)::               lhs,rhs
    character(len=sizeof(lhs),kind=1):: lb
    character(len=sizeof(rhs),kind=1):: rb
    integer(ip)::                       i
        r   = .false.
        if(.not.same_type_as(lhs,rhs))  return
        if(.not.len(lb)==len(rb))       return
        lb  = transfer(lhs,mold=lb)
        rb  = transfer(rhs,mold=rb)
        r   = lb == rb
    end function anyiseq2
    
end program main

 

here i compare two unlimited polymorphism types byte by byte

i tested two methods with debug mode, and i received <access violation> for the second one at line

lb  = transfer(lhs,mold=lb)

 

is this a bug or i missed something?

i use the vs2015+ifort2017u4

 

and more

for now, i just have tested this function for some simple derived type.

i wonder anyone have experience about this method and knows whether it's a proper way to compare any types

0 Kudos
6 Replies
JVanB
Valued Contributor II
679 Views

I think the issue here is that the Fortran language does not require the Fortran processor to be able to construct a derived type from an unlimited polymorphic descriptor at run time the way that interpreted languages such as Matlab can. Since the processor doesn't know how to construct the type in the specification part of the procedures, it has no way of knowing what SIZEOF(lhs) should return, for example. Thus ifort should simply produce an error at compile time. That's why you need a SELECT TYPE construct to do much with an unlimited polymorphic entity, however you can't put a SELECT TYPE construct in the specification part of a procedure, and besides SELECT TYPE kind of takes all the fun out of unlimited polymorphism.

When I remove the ELEMENTAL attribute from function anyiseq and print out SIZE(lhs) there and LEN(lhs) in function anyiseq2, ifort 16.0 prints out 0 in both cases. gfortran 5.3 just hangs at runtime without reaching the WRITE statements. Thus there isn't any problem with TRANSFER in function anyiseq because the size of the MOLD= array is ignored, but there is a problem in function anyiseq2 because of the CHARACTER(LEN=0) MOLD= argument to TRANSFER. Actually, this runs to completion in ifort 16.0, so this may be a regression in ifort2017u4. What happens if you try something like

program P
   implicit none
   character(LEN=0) C
   type T
      sequence
   end type T
   type(T) A
   write(*,*) F(C,A)
   contains
      function F(X,Y)
         integer F
         character(LEN=*) X
         type(T) Y
         X = TRANSFER(Y,X)
         F = INDEX(X,'A')
      end function F
end program P

Does this also cause an access violation?

 

0 Kudos
Li_L_
New Contributor I
679 Views

Repeat Offender wrote:

I think the issue here is that the Fortran language does not require the Fortran processor to be able to construct a derived type from an unlimited polymorphic descriptor at run time the way that interpreted languages such as Matlab can. Since the processor doesn't know how to construct the type in the specification part of the procedures, it has no way of knowing what SIZEOF(lhs) should return, for example. Thus ifort should simply produce an error at compile time. That's why you need a SELECT TYPE construct to do much with an unlimited polymorphic entity, however you can't put a SELECT TYPE construct in the specification part of a procedure, and besides SELECT TYPE kind of takes all the fun out of unlimited polymorphism.

When I remove the ELEMENTAL attribute from function anyiseq and print out SIZE(lhs) there and LEN(lhs) in function anyiseq2, ifort 16.0 prints out 0 in both cases. gfortran 5.3 just hangs at runtime without reaching the WRITE statements. Thus there isn't any problem with TRANSFER in function anyiseq because the size of the MOLD= array is ignored, but there is a problem in function anyiseq2 because of the CHARACTER(LEN=0) MOLD= argument to TRANSFER. Actually, this runs to completion in ifort 16.0, so this may be a regression in ifort2017u4. What happens if you try something like

program P
   implicit none
   character(LEN=0) C
   type T
      sequence
   end type T
   type(T) A
   write(*,*) F(C,A)
   contains
      function F(X,Y)
         integer F
         character(LEN=*) X
         type(T) Y
         X = TRANSFER(Y,X)
         F = INDEX(X,'A')
      end function F
end program P

Does this also cause an access violation?

 

sizeof(lhs) gives the right answer (4), by ifort2017u4

it seems <size> and <len> don't work for class(*), but not including <sizeof>

 

your code runs well and no access violation. it prints 0.

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
679 Views

Li L

Should your type contain an allocatable component, the byte-by-byte compares will be comparing the array descriptors and not the contents of the identical contented arrays. Thus identical types will fail equality test.

Jim Dempsey

0 Kudos
Li_L_
New Contributor I
679 Views

thanks for your advice

and i will pay attention to the limitation of this function

 

and can you reproduce the access violation and knows why?

0 Kudos
FortranFan
Honored Contributor II
679 Views

Li L. wrote:

thanks for your advice

and i will pay attention to the limitation of this function

 

and can you reproduce the access violation and knows why?

Try using standard intrinsic function STORAGE_SIZE: https://software.intel.com/en-us/fortran-compiler-18.0-developer-guide-and-reference-storage-size

Look into CHARACTER_STORAGE_SIZE and NUMERIC_STORAGE_SIZE also in connection with this: https://software.intel.com/en-us/fortran-compiler-18.0-developer-guide-and-reference-named-constants-1

Also, post at Intel's Online Service Center (OSC) to get an answer from Intel staff as to why the access violation occurs: https://software.intel.com/en-us/articles/how-to-create-a-support-request-at-online-service-center.

Separately, though, you may want to rethink what you're trying to do and ask yourself whether you really need functions such as the two you show; for intrinsic types, use intrinsic capabilities and for your derived types, can you not include defined comparison operators?  By the way, I suggest staying from SEQUENCE types if you can.

0 Kudos
Li_L_
New Contributor I
679 Views

FortranFan wrote:

Quote:

Li L. wrote:

 

thanks for your advice

and i will pay attention to the limitation of this function

 

and can you reproduce the access violation and knows why?

 

 

Try using standard intrinsic function STORAGE_SIZE: https://software.intel.com/en-us/fortran-compiler-18.0-developer-guide-a...

Look into CHARACTER_STORAGE_SIZE and NUMERIC_STORAGE_SIZE also in connection with this: https://software.intel.com/en-us/fortran-compiler-18.0-developer-guide-a...

Also, post at Intel's Online Service Center (OSC) to get an answer from Intel staff as to why the access violation occurs: https://software.intel.com/en-us/articles/how-to-create-a-support-reques....

Separately, though, you may want to rethink what you're trying to do and ask yourself whether you really need functions such as the two you show; for intrinsic types, use intrinsic capabilities and for your derived types, can you not include defined comparison operators?  By the way, I suggest staying from SEQUENCE types if you can.

as your advice, i'm refactoring my code

i'm just practicing the structure of hashmap

for the first time, i want to use the class(*) for simplicity, and write the function above

but now, i think i can just transfer all of possible data(just simple derived type and native type) to integer array

and integer's operator(==) is much faster than character's operator(==)

 

SEQUENCE is a good advice 

 

 

 

0 Kudos
Reply