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

compilation hangs with -g flag, undefined references when linking on 64bit RHEL but not 32 bit Ubuntu

Izaak_Beekman
New Contributor II
617 Views
I am seeing some very odd behavior when compiling on different machines. The following code compiles and runs as expected on 32 bit Ubuntu (with ifort 11.1.046 non-commercial) but on x86_64 RHEL running the full on commercial version of ifort 11.1.046 throwing the -g flag causes compilation to hang. Also unless you call the sllist procedures by their module procedure name, rather than their type bound name, without the -g the code will compile but you will get segfaults on the 64 bit machine. If you call all functions by their module procedure name (from within the modhashtbl.f90 module) the code runs correctly on both machines, but still hangs on 64 bit RHEL when compiled with -g.
In general I have found the type bound procedures and many other OOP Fortran 2003 features essentially a waste of time due to unpredictable behavior. I wouldrecommendmore testing before declaring features as "implemented."
Here is the module:
[fortran]! Copyright (c) Izaak Beekman 2010

    ! This program is free software: you can redistribute it and/or modify
    ! it under the terms of the GNU Lesser General Public License as published by
    ! the Free Software Foundation, either version 3 of the License, or
    ! (at your option) any later version.

    ! This program is distributed in the hope that it will be useful,
    ! but WITHOUT ANY WARRANTY; without even the implied warranty of
    ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    ! GNU Lesser General Public License for more details.

    ! You should have received a copy of the GNU Lesser General Public License
    ! along with this program.  If not, see <>.

MODULE hashtbl
  IMPLICIT NONE ! Use strong typing
  INTEGER, PARAMETER :: tbl_size = 50

  TYPE sllist
     TYPE(sllist), POINTER :: child => NULL()
     CHARACTER(len=:), ALLOCATABLE :: key, val
   CONTAINS
     PROCEDURE :: put  => put_sll
     PROCEDURE :: get  => get_sll
     PROCEDURE :: free => free_sll
  END TYPE sllist

  TYPE hash_tbl_sll
     TYPE(sllist), DIMENSION(:), ALLOCATABLE :: vec
     INTEGER                                 :: vec_len = 0
     LOGICAL                                 :: is_init = .FALSE.
   CONTAINS
     PROCEDURE :: init => init_hash_tbl_sll
     PROCEDURE :: put  => put_hash_tbl_sll
     PROCEDURE :: get  => get_hash_tbl_sll
     PROCEDURE :: free => free_hash_tbl_sll
  END TYPE hash_tbl_sll
  
  PUBLIC :: hash_tbl_sll

CONTAINS

  RECURSIVE SUBROUTINE put_sll(list,key,val)
    CLASS(sllist),    INTENT(inout) :: list
    CHARACTER(len=*), INTENT(in)    :: key, val
    INTEGER                         :: keylen, vallen

    keylen = LEN(key)
    vallen = LEN(val)
    IF (ALLOCATED(list%key)) THEN
       IF (list%key /= key) THEN
          IF ( .NOT. ASSOCIATED(list%child) ) ALLOCATE(list%child)
          CALL put_sll(list%child,key,val)
       END IF
    ELSE
       IF (.NOT. ALLOCATED(list%key)) &
            ALLOCATE(CHARACTER(len=keylen) :: list%key)
       list%key = key
       IF (ALLOCATED(list%val)) DEALLOCATE(list%val)
       ALLOCATE(CHARACTER(len=vallen) :: list%val)
       list%val = val
    END IF
  END SUBROUTINE put_sll


  RECURSIVE SUBROUTINE get_sll(list,key,val)
    CLASS(sllist),                 INTENT(in)    :: list
    CHARACTER(len=*),              INTENT(in)    :: key
    CHARACTER(len=:), ALLOCATABLE, INTENT(out)   :: val
    INTEGER                                      :: vallen

    vallen = 0
    IF (ALLOCATED(list%key) .AND. (list%key == key)) THEN
       vallen = LEN(list%val)
       IF (ALLOCATED(val)) DEALLOCATE(val)
       ALLOCATE(CHARACTER(len=vallen) :: val)
       val = list%val
    ELSE IF(ASSOCIATED(list%child)) THEN ! keep going
       CALL get_sll(list%child,key,val)
    ELSE ! At the end of the list, no key found
       IF (ALLOCATED(val)) DEALLOCATE(val) ! Exit indication
       RETURN
    END IF
  END SUBROUTINE get_sll
  

  RECURSIVE SUBROUTINE free_sll(list)
    CLASS(sllist), INTENT(inout) :: list
    IF (ASSOCIATED(list%child)) THEN
       CALL free_sll(list%child)
       DEALLOCATE(list%child)
    END IF
    list%child => NULL()
    IF (ALLOCATED(list%key)) DEALLOCATE(list%key)
    IF (ALLOCATED(list%val)) DEALLOCATE(list%val)
  END SUBROUTINE free_sll
  
  SUBROUTINE init_hash_tbl_sll(tbl,tbl_len)
    CLASS(hash_tbl_sll),   INTENT(inout) :: tbl
    INTEGER,     OPTIONAL, INTENT(in)    :: tbl_len

    IF (ALLOCATED(tbl%vec)) DEALLOCATE(tbl%vec)
    IF (PRESENT(tbl_len)) THEN
       ALLOCATE(tbl%vec(0:tbl_len-1))
       tbl%vec_len = tbl_len
    ELSE
       ALLOCATE(tbl%vec(0:tbl_size-1))
       tbl%vec_len = tbl_size
    END IF
    tbl%is_init = .TRUE.
  END SUBROUTINE init_hash_tbl_sll
  
  ! The first part of the hashing procedure using the string
  ! collating sequence
  ELEMENTAL FUNCTION sum_string(str) RESULT(sig)
    CHARACTER(len=*), INTENT(in)   :: str
    INTEGER                        :: sig
    CHARACTER, DIMENSION(LEN(str)) :: tmp
    INTEGER :: i
    
    FORALL (i=1:LEN(str))
       tmp(i) = str(i:i)
    END FORALL
    sig = SUM(ICHAR(tmp))
  END FUNCTION sum_string
  

  SUBROUTINE put_hash_tbl_sll(tbl,key,val)
    CLASS(hash_tbl_sll), INTENT(inout) :: tbl
    CHARACTER(len=*),    INTENT(in)    :: key, val
    INTEGER                            :: hash
    
    hash = MOD(sum_string(key),tbl%vec_len)
    CALL tbl%vec(hash)%put(key=key,val=val) ! Call via module procedure name to run error free
                                            ! on x86_64 RHEL 5
  END SUBROUTINE put_hash_tbl_sll
  

  SUBROUTINE get_hash_tbl_sll(tbl,key,val)
    CLASS(hash_tbl_sll),           INTENT(in)    :: tbl
    CHARACTER(len=*),              INTENT(in)    :: key
    CHARACTER(len=:), ALLOCATABLE, INTENT(out)   :: val
    INTEGER                                      :: hash
    
    hash = MOD(sum_string(key),tbl%vec_len)
    CALL tbl%vec(hash)%get(key=key,val=val) ! Call via module procedure name to run error free
                                            ! on x86_64 RHEL 5
  END SUBROUTINE get_hash_tbl_sll
  

  SUBROUTINE free_hash_tbl_sll(tbl)
    CLASS(hash_tbl_sll), INTENT(inout) :: tbl    
    INTEGER     :: i, low, high

    low  = LBOUND(tbl%vec,dim=1)
    high = UBOUND(tbl%vec,dim=1) 
    IF (ALLOCATED(tbl%vec)) THEN
       DO i=low,high
          CALL tbl%vec(i)%free() ! Call via module procedure name to run error free
                                 ! on x86_64 RHEL 5
       END DO
       DEALLOCATE(tbl%vec)
    END IF
    tbl%is_init = .FALSE.
  END SUBROUTINE free_hash_tbl_sll

END MODULE hashtbl
[/fortran]
Here is the test program:
[fortran]! Copyright (c) Izaak Beekman 2010

    ! This program is free software: you can redistribute it and/or modify
    ! it under the terms of the GNU Lesser General Public License as published by
    ! the Free Software Foundation, either version 3 of the License, or
    ! (at your option) any later version.

    ! This program is distributed in the hope that it will be useful,
    ! but WITHOUT ANY WARRANTY; without even the implied warranty of
    ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    ! GNU Lesser General Public License for more details.

    ! You should have received a copy of the GNU Lesser General Public License
    ! along with this program.  If not, see <>.

PROGRAM test_hashtbl
  USE hashtbl
  IMPLICIT NONE
  TYPE(hash_tbl_sll)            :: table
  CHARACTER(len=:), ALLOCATABLE :: out
  INTEGER, parameter :: tbl_length = 100
  INTEGER            :: sum, i, rand_int1, rand_int2 ! 4 byte integer, hopefully
  REAL               :: rand
  CHARACTER(len=4)   :: rand_str1, rand_str2 ! each char should be 1 byte
  
  PRINT*, ' '
  PRINT*, 'This program is free software: you can redistribute it and/or &
       &modify it under the terms of the GNU Lesser General Public License&
       & as published by the Free Software Foundation, either version 3 of&
       & the License, or (at your option) any later version.'
  PRINT*, ' '
  PRINT*, 'This program is distributed in the hope that it will be useful,&
       & but WITHOUT ANY WARRANTY; without even the implied warranty of&
       & MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the &
       &GNU Lesser General Public License for more details.'
  PRINT*, ' '
  PRINT*, 'You should have received a copy of the GNU Lesser General Public &
       &License along with this program.  If not, see &
       &<>.'
  PRINT*, ' '

  CALL table%init(tbl_length)
  CALL table%put(key='first_name', val='John')
  PRINT*, 'Hash: ', MOD(sum_string('first_name'),tbl_length)
  CALL table%put(key='last_name', val='Smith')
  PRINT*, 'Hash: ', MOD(sum_string('last_name'),tbl_length)
  CALL table%put(key='birthday', val='July 30, 1964')
  PRINT*, 'Hash: ', MOD(sum_string('birthday'),tbl_length)
  CALL table%put(key='hair_color', val='brown')
  PRINT*, 'Hash: ', MOD(sum_string('hair_color'),tbl_length)
  CALL table%put(key='eye_color', val='brown')
  PRINT*, 'Hash: ', MOD(sum_string('eye_color'),tbl_length)
  CALL table%put(key='weight', val='213 lbs')
  PRINT*, 'Hash: ', MOD(sum_string('weight'),tbl_length)
  CALL table%put(key='height', val='6''3"')
  PRINT*, 'Hash: ', MOD(sum_string('height'),tbl_length)

  PRINT*, ' ' 

  CALL table%get(key='first_name',val=out)
  PRINT*, out
  CALL table%get('last_name',out)
  PRINT*, out
  CALL table%get('birthday',out)
  PRINT*, out
  CALL table%get('hair_color',out)
  PRINT*, out
  CALL table%get('eye_color',out)
  PRINT*, out
  CALL table%get('weight',out)
  PRINT*, out
  CALL table%get('height',out)
  PRINT*, out

!  INCLUDE 'stress_test.f90'

  PRINT*, ' '
  
  sum = 0
  PRINT*, 'Indices of the hash table with content:'
  DO i = LBOUND(table%vec,dim=1), UBOUND(table%vec,dim=1)
     IF (ALLOCATED(table%vec(i)%key)) THEN 
        PRINT*, i
        sum = sum + 1
     END IF
  END DO
  PRINT*, 'Total used elements:', sum
  CALL table%free
  PRINT*, ' '
  STOP 0
END PROGRAM test_hashtbl
[/fortran]
0 Kudos
4 Replies
Izaak_Beekman
New Contributor II
617 Views
This was marked private, but no one replied, so I am making it visible to all, in hopes that someone will reply.
0 Kudos
Kevin_D_Intel
Employee
617 Views

Thank you for the convenient reproducer. Our apologies for the lack of an earlier reply; the private designation was not an issue. I will investigate the described issues and update this post as I learn more.

0 Kudos
mecej4
Honored Contributor III
617 Views
Using version 11.1.072 on x86_64 Suse-11.1, I did not encounter the problems described.
0 Kudos
Kevin_D_Intel
Employee
617 Views

As mecej4 indicated, version 11.1.072 (11.1 Update 6) does not exhibit the problems described. I did not experience the compilation hang with g but rather an internal compiler error with that when compiling modhashtble.f90. With some help I also verified the program runs correctly when calling the type bound names.

Thank you mecej4.

0 Kudos
Reply