Fortran Attempt to fetch from allocatable variable when it is not allocated - 小众知识

Fortran Attempt to fetch from allocatable variable when it is not allocated

2022-11-18 14:03:39 苏内容
  标签: Fortran
阅读:2664

Using ifort 11.1.046 with -check all, I get "forrtl: severe (408): fort: (8): Attempt to fetch from allocatable variable VALUES when it is not allocated" at runtime, but I don't understand why. As far as I can tell, img1%values and img2%values are allocated. What am I doing wrong?


[cpp]module image_mod

	type image
		real, allocatable :: values(:)
	end type image

	interface assignment(=)
		module procedure image_assignment
	end interface

	interface operator(+)
		module procedure add_images
	end interface

	contains

		function add_images(img1,img2) result(imgout)
			implicit none
			type(image), intent(in) :: img1, img2
			type(image) :: imgout
			imgout%values = img1%values + img2%values
		end function

		subroutine image_assignment(imgout,imgin)
			implicit none
			type(image), intent(out) :: imgout
			type(image), intent(in)  :: imgin
			imgout%values = imgin%values
		end subroutine

end module image_mod

program images
	use image_mod
	implicit none

	type(image) :: img1, img2
	integer :: ierr

	allocate(img1%values(5), img2%values(5), stat=ierr)
	if (ierr == 0) write(*,*) 'Allocation successful'

	img1%values = 1.0
	img2%values = 2.0

	img2 = img1 + img2

	write(*,*) img2%values
end program images
[/cpp]


http://software.intel.com/en-us/forums/showthread.php?t=65456
indicates possibility of known bugs


Compile with: -assume realloc_lhs

The thread (here) may be of interest/value too.



Compile with: -assume realloc_lhs

The thread (here) may be of interest/value too.


Kevin,

Thanks for the hint. Using this option does remove the runtime error. However, it seems to me that this option is almost exactly the opposite of the behaviour I would want. I would much rather have a segfault if trying to write to an unallocated array or an array allocated the wrong size rather than duplicate or reallocate large arrays on the fly like the documentation for -assume realloc_lhs seems to imply:

Tells the compiler that when the left-hand side of an assignment is an allocatable object, it should be reallocated to the shape of the right-hand side of the assignment before the assignment occurs. This is the Fortran 2003 definition. This feature may cause extra overhead at run time.


(In fact, I don't really understand what this sentence means in detail. Is the entity on the left-hand side always reallocated, even when its shape already matches that of the right-hand side?)

Further, I feel there is an inconsistency at play. If I replace line 46 above with the line below, I don't have an error anymore at runtime.

[cpp]	img2%values = img1%values + img2%values[/cpp]

So the error I was getting ("Attempt to fetch from allocatable variable when it is not allocated") must have been plain wrong, since img1%values and img2%values can be read from and written to perfectly well with the line above. To my layman's eyes, this looks like buggy behaviour when checking the allocation status of allocatable arrays within derived types vs. allocatable arrays themselves.



Quoting - tim18



Thanks for the link, my issue does seem related, in that it looks to me like in my case the checks for the allocation status of an array is dodgy when that array is within a derived type and isn't directly refered to in the assignment.



When I tried to run a huge Fortran code (the code is compiled using Intel compiler version 13.1.3.192), it gave me error message like this:

... 
Info[FDFI_Setup]: HPDF code version number is  1.00246
forrtl: severe (153): allocatable array or pointer is not allocated
Image              PC                Routine            Line        Source
arts               0000000002AD96BE  Unknown               Unknown  Unknown
arts               0000000002AD8156  Unknown               Unknown  Unknown
arts               0000000002A87532  Unknown               Unknown  Unknown
...

Nonetheless, if I insert a small write statement (which is just to check the code, not to disturb the original purpose of the code) in one of the subroutines as the following (I couldn't put all the codes since they are too huge):

    ...
    endif
    call GetInputLine(Unit,line,eof,err)
  enddo

  if(err) return

  ! - [elfsummer] 20140815 Checkpoint 23
  open(unit = 1, file = '/bin/monitor/log_checkpoint',status='old',position='append')
  write(1,*) "BEFORE checking required keys: so far so good!"
  close(1)

  ! check required keys
  ! for modes = 2,3, P and T are the required keys
  if(StrmDat%ModeCI==2.or.StrmDat%ModeCI==3) then
  ...

then suddenly, the error message shown above disappears and the code can run correctly! I also tried to insert such write statements in other locations in the source code but the above error message still exists.

According to Intel's documentation:

severe (153): Allocatable array or pointer is not allocated FOR$IOS_INVDEALLOC. A Fortran 90 allocatable array or pointer must already be allocated when you attempt to deallocate it. You must allocate the array or pointer before it can again be deallocated. Note: This error can be returned by STAT in a DEALLOCATE statement.

However, I couldn't see any relations between the error and the "write statements" I added to the code. There is no such "allocate" command in the location I add the write statements.

So I am quite confused. Does anybody know the reasons? Any help is greatly appreciated!!

With traceback option, I could locate the error source directly:

    subroutine StringRead(Str,delimiter,StrArray,ns)   ! [private] read strings separated by    delimiter
    implicit none
    character*(*),intent(in)    :: Str
    character*(*),intent(in)    :: delimiter
    character*(*),pointer       :: StrArray(:)
    integer,intent(out)         :: ns
! - local variables
    character(len=len(Str))     :: tline
    integer                     :: nvalue,nvalue_max
    character(len=len(StrArray)),pointer:: sarray(:),sarray_bak(:)
    integer                     :: len_a,len_d,i

    ! deallocate StrArray
    if(associated(StrArray)) deallocate(StrArray)

The error, according to the information the traceback gave me, lies in the last statement shown above. If I comment out this statement, then the "forrtl: severe (153)" error would disappear while new errors being generated... But still, I don't think this statement itself could go wrong...It acts as if it just ignores the if... condition and directly reads the deallocate commend, which seems weird to me.

 

You could have a bug in which you are illegally writing to memory and damaging the structure that stores the allocation information. Changing the code might cause the memory damage to occur elsewhere and that specific error to disappear. Generally, illegal memory accesses typically occur two ways in Fortran. 1) illegal subscripts, 2) mismatch between actual and dummy arguments, i.e., between variables in call and variables as declared in procedures. You can search for the first type of error by using your compiler's option for run-time subscript checking. You can guard against the second by placing all of your procedures in modules and useing those modules so that the compiler can check for argument consistency.



扩展阅读
相关阅读
© CopyRight 2010-2021, PREDREAM.ORG, Inc.All Rights Reserved. 京ICP备13045924号-1