Recursive function (with allocatable inside)



Hi,

I continue to experiment some bugs while using derived-types
based on allocatable arrays. So I worked to reduce the problem and
the following is a small source code which contains a recursive
function
which returns a derived-type, which contains an allocatable array.
It tries to compute a tree, for which each node has 3 leaves.
Several versions of the code are possible, depending on the following
parameters:
- the level of recursive calls (I tried 1 and 2 levels),
- use allocatable or pointer arrays,
- use a subroutine or a function (yes, I tried that !).
With 1 level of recursion, the tree has 12 leaves, and with
2 levels, the tree has 39 leaves (the root is not counted).
I tried 3 compilers : Intel Fortran 8, gfortran and g95.
By making these parameters vary, I generated a family of bug,
which could be called a bug farm ...

module mymodule
implicit none
type, public :: t_dt
! Or : integer , dimension (:), pointer :: array
integer , dimension (:), allocatable :: array
end type t_dt
integer :: currentid = 0
contains
! Or : recursive subroutine mysub ( level , stufflist )
recursive function myfunc ( level ) result ( stufflist )
integer , intent(in) :: level
type ( t_dt ) :: stufflist
type ( t_dt ) :: stufflist_copy
type ( t_dt ) :: stufflist_sublevel
integer , parameter :: maxchild = 3
integer :: myindex
integer :: current_size
integer :: newsize
integer :: sublevelsize
!
! Compute the current direct children
!
allocate ( stufflist % array ( maxchild ) )
do myindex = 1 , maxchild
currentid = currentid + 1
stufflist % array ( myindex ) = currentid
enddo
! Or : if ( level == 2 ) then
if ( level == 1 ) then
return
endif
!
! Loop over the children
!
do myindex = 1 , maxchild
!
! Compute the children from sub-levels
!
stufflist_sublevel = myfunc ( level + 1 )
!
! Append the children of sub-levels to the current list
!
current_size = size ( stufflist % array )
allocate ( stufflist_copy % array ( current_size ) )
stufflist_copy % array = stufflist % array
deallocate ( stufflist % array )
sublevelsize = size ( stufflist_sublevel % array )
newsize = current_size + sublevelsize
allocate ( stufflist % array ( newsize ) )
stufflist % array ( 1 : current_size ) = stufflist_copy % array
( 1 : current_size )
stufflist % array ( current_size + 1 : newsize ) =
stufflist_sublevel % array ( 1 : sublevelsize )
deallocate ( stufflist_copy % array )
deallocate ( stufflist_sublevel % array )
enddo
end function myfunc
end module mymodule
program test1
use mymodule
implicit none
type ( t_dt ) :: stufflist
integer :: myindex
integer :: arraysize
stufflist = myfunc ( 0 )
arraysize = size ( stufflist % array )
do myindex = 1 , arraysize
write(12,*) "[", myindex , "]" , stufflist % array ( myindex )
enddo
end program test1

These are the version of the compilers I used :
Intel Fortran :
(recursivefunc_withdt) 73 % ifort -h
Intel(R) Fortran Compiler for 32-bit applications, Version 8.0 Build
20031017Z Package ID: w_fc_p_8.0.034
Copyright (C) 1985-2003 Intel Corporation. All rights reserved.

(recursivefunc_withdt) 73 % g95 -v
Using built-in specs.
Target:
Configured with: /src/G95/gcc-4.0-20060302/configure --with-gcc --with-
gnu-ld --with-ld=/mingw/bin/ld --with-gnu-as --with-as=/mingw/bin/as --
host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --
disable-nls --enable-languages=c --disable-win32-registry --disable-
shared --without-x --disable-libmudflap --disable-libssp
Thread model: win32
gcc version 4.0.3 (g95 0.91!) May 3 2007

gfortran :
(recursivefunc_withdt) 74 % gfortran -v
Using built-in specs.
Target: i586-pc-mingw32
Configured with: ../trunk/configure --prefix=/mingw --enable-
languages=c,fortran --with-gmp=/home/FX/local --with-ld=/mingw/bin/ld
--with-as=/mingw/bin/as --disable-werror --enable-bootstrap --enable-
threads --disable-nls --build=i586-pc-mingw32 --enable-libgomp --
disable-shared
Thread model: win32
gcc version 4.4.0 20080312 (experimental) [trunk revision 133139]
(GCC)

This is a sample result with gfortran and 2 levels :
(recursivefunc_withdt) 58 % gfortran test4.f90 -o test4.exe
(recursivefunc_withdt) 59 % test4.exe
[ 1 ] 1
[ 2 ] 2
[ 3 ] 3
[ 4 ] 4
[ 5 ] 5
[ 6 ] 6
[ 7 ] 7
[ 8 ] 8
[ 9 ] 9
[ 10 ] 10
[ 11 ] 11
[ 12 ] 12
[ 13 ] 13
[ 14 ] 14
[ 15 ] 15
[ 16 ] 16
[ 17 ] 17
[ 18 ] 18
[ 19 ] 19
[ 20 ] 20
[ 21 ] 21
[ 22 ] 22
[ 23 ] 23
[ 24 ] 24
[ 25 ] 25
[ 26 ] 26
[ 27 ] 27
[ 28 ] 28
[ 29 ] 29
[ 30 ] 30
[ 31 ] 31
[ 32 ] 32
[ 33 ] 33
[ 34 ] 34
[ 35 ] 35
[ 36 ] 36
[ 37 ] 37
[ 38 ] 38
[ 39 ] 39

These are the results I got, depending on the source code.

test2 : function, allocatable, level 1
gfortran : OK
Intel Fortran : OK

test3 : function, allocatable, level 2
gfortran : OK
Intel Fortran : FALSE
g95 : OK

test4 : function, pointer, level 2
gfortran : OK
Intel Fortran : Exception
g95 : OK

test5 : subroutine, allocatable, level 2
gfortran : child killed: segmentation violation
Intel Fortran : OK !
g95 : OK

I was not really surprised to find out that gfortran had some
problems, because I have allready reported a bug for gfortran :
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35959
which has been fixed several week ago.
So I will try the same code with the next release of gfortran.

What was more surprising to me is that Intel Fortran works
in that particular case with recursive subroutines and
not with recursive functions.
Another thing which is strange to me is that the allocatable
version runs with wrong results, whereas the pointer
version fails with a runtime exception.

This is an abstract of the call stack when Intel Fortran
fails with 2 levels, pointer array and function :
...>_for_deallocate>free>_free_dbg > _CrtIsValidHeapPointer

This is the wrong result for the Intel Fortran compiler,
2 levels, allocatable array and function :
[ 1 ] 1
[ 2 ] 2
[ 3 ] 3
[ 4 ] 13
[ 5 ] 14
[ 6 ] 15
[ 7 ] 13
[ 8 ] 14
[ 9 ] 15
[ 10 ] 25
[ 11 ] 26
[ 12 ] 27
[ 13 ] 25
[ 14 ] 26
[ 15 ] 27
[ 16 ] 37
[ 17 ] 38
[ 18 ] 39
[ 19 ] 37
[ 20 ] 38
[ 21 ] 39

I looked at the release notes for the Intel Fortran Compilers (8, 9,
10), but
I did not find any comments on that particular problem.

It is difficult for me to find a practical conclusion for this.
Should I update my Intel compiler for the 10. release ?
Should I use subroutines instead of functions : stupid conclusion,
but would solve the problem !

Regards,

Michaël




.



Relevant Pages

  • Re: gfortran: bug or non-standard syntax?
    ... are changed are almost always the result of accessing an array (writing ... as any software gfortran is neither bugfree nor feature ... warn all -stand f03" when you compile with ifort and check whether you ... If you think this is a bug in gfortran, feel free to fill a bug ...
    (comp.lang.fortran)
  • Re: GFortran run time error codes. Where to find them?
    ... GFortran generates for DE/ALLOCATE STAT and READ/WRITE IOSTAT specifiers ... Array reference out of bounds ... therefore I may assume they do not contain any bug. ... else which could cause memory problems besides allocatable arrays? ...
    (comp.lang.fortran)
  • Re: The : operator
    ... Intel Fortran 7.1 is rather primitive when it comes to things such as this. ... But if the array is a local array and is not allocatable or pointer, ... Software Products Division ...
    (comp.lang.fortran)
  • Re: Poor performance of implied-DO loop with Intel Fortran
    ... >I get very poor performance when using implied-DO loops to initialise ... The performance is fine with loops up to one hundred ... the implied DO loop on Intel Fortran 8.0 Build 20040415Z and it compiled fine. ... it needed the stack expanded because of the large temporary array ...
    (comp.lang.fortran)
  • Re: Creating a python c-module: passing double arrays to c functions. segmentation fault. swig
    ... The dtype should be the datatype kept in the array, ... which is 'float' (Python doubles) or 'numpy.float64'. ... I would be valid C99, but you are not compiling it as C99 (gcc does ... get gfortran or Intel Fortran. ...
    (comp.lang.python)