|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
simon
Joined: 05 Jul 2006 Posts: 270
|
Posted: Thu Apr 20, 2023 1:42 am Post subject: Shape of deallocated array |
|
|
In the following program, FTN95 remembers the shape of the allocatable array after it is deallocated. In other compilers the call to Shape generates a run-time error.
Code: | Program p
Integer, Dimension(:), Allocatable :: i
Allocate (i(2))
Deallocate (i)
Print*, Shape(i), Allocated(i)
End Program p
|
In my larger programme I am getting inconsistent behaviour when it is rerun with exactly the same inputs. I am wondering whether this problem is somehow related. Occasionally it seems that FTN95 returns an error when trying to reallocate this memory (I am using IOSTAT=, which returns 1), although I can confirm that allocated (i) is false before the call. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
Posted: Thu Apr 20, 2023 7:11 am Post subject: |
|
|
Simon
I am not sure if I can provide any assistance on this issue but some details might depend on whether or not it is 64 or 32 bits, CHECK or not CHECK. |
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 270
|
Posted: Thu Apr 20, 2023 7:33 am Post subject: |
|
|
Hi Paul,
I seem to get the same output ("2 F") regardless of which compiler options I use. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
Posted: Thu Apr 20, 2023 12:44 pm Post subject: |
|
|
Simon
I don't see how the problem could relate to the shape of an array after deallocate. FTN95 will allocate memory for a pointer to the allocated block and presumably for the returned shape. The pointer will be reset to NULL on deallocate but I guess that the shape won't be reset.
An IOSTAT value of 1 means that the resulting call to HeapAlloc has failed which in turn means that that there is insufficient memory or that the heap is corrupted. There is also the possibility that the requested size of the block of memory has got corrupted.
I presume that you have run tests using /CHECKMATE. |
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 270
|
Posted: Thu Apr 20, 2023 4:12 pm Post subject: |
|
|
Indeed, I have tried CHECKMATE. But forgetting about the larger programme for now, is Shape not returning an incorrect result even in the simple example? Size also returns 2 after i is deallocated. |
|
Back to top |
|
|
Kenneth_Smith
Joined: 18 May 2012 Posts: 709 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Fri Apr 21, 2023 1:44 am Post subject: |
|
|
The 2008 (draft) standard explicitly states that the argument of both SHAPE and SIZE must not be an unallocated allocatable variable. So what a complier should or should not return in this case is not clearly defined. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
Posted: Fri Apr 21, 2023 7:44 am Post subject: |
|
|
What FTN95 actually does after DEALLOCATE can be discovered by using /EXPLIST on the command line and decyphering the resultant listing but I don't think that it will have any bearing on the current problem.
Add some code locally to get the shape so that you can see how it relates to the registers and associated memory allocation. |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1896
|
Posted: Fri Apr 21, 2023 1:44 pm Post subject: |
|
|
Line 5 of the short program in the first post has two function invocations in the output list, one of which is legal and the other is not. If we separate the two, as in
Code: | Program p
Integer, Dimension(:), Allocatable :: i
Allocate (i(2))
Deallocate (i)
Print*, Shape(i) ! not legal, since i is not currently allocated
Print *, Allocated(i) ! legal
End Program p |
it is easier to discuss what the program may be expected to do, when it is compiled with and without /check.
When /check has not been used, the use of Shape(i) when the variable I is currently not allocated is incorrect, the program behaviour is undefined and it can do anything.
I think that when /check has been used the modified program should be able to detect the reference to Shape with an argument that is currently not allocated, issue an appropriate message, and abort execution. FTN95 currently does not do this, and a fix may be worth considering.
For this program, after compiling and linking with Lahey Fortran with the -Hx option, the program terminates with the output:
Code: | jwe0324i-w line 5 Allocatable array (i) is not allocated.
error occurs at _MAIN__ line 5 loc 004010ce offset 000000ce
_MAIN__ at loc 00401000 called from o.s. |
|
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 270
|
Posted: Sat Apr 29, 2023 4:37 pm Post subject: |
|
|
Many thanks to everyone's inputs. It has been helpful to know not to expect shape to "work" (if that is the correct word) when its argument is deallocated.
I don't know whether this is a closely related problem, but in trying to trace the memory issues I referred to before, I encountered the following issue:
Code: |
print *, shape(b),shape(a)
b(:,:) = a(:,:,1)
print *, shape(b)
|
a and b are both allocated, and in one example where this problem happens I get the following output:
I will see if I can create a small example of code to reproduce this problem ... |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2580 Location: Sydney
|
Posted: Sun Apr 30, 2023 12:44 pm Post subject: |
|
|
If "b" is deallocated, then I would expect shape(b) is undefined for values and also possibly for rank ?
For "b(:,:) = a(:,:,1)" I am not sure if auto-allocate applies, although the following code example does not show this for both FTN95 and Gfortran.
I am unsure when auto-allocate does apply so I try to avoid this syntax.
Does the following code example help ?
It does not reproduce your post result
Code: | ! test of auto allocate
integer, allocatable :: a(:,:,:)
integer, allocatable :: b(:,:)
integer :: i,j,k
allocate ( a(4,7,3) )
allocate ( b(4,6) )
do k = 1,3
do j = 1,7
do i = 1,4
a(i,j,k) = i+j+k
end do
end do
end do
do j = 1,6
do i = 1,4
b(i,j) = i+j+4
end do
end do
print *, 'a', shape(a), size(a)
print *, 'b', shape(b), size(b)
b(:,:) = a(:,:,1) ! not sure what happens here
print *, 'b', shape(b), size(b)
do j = 1,6
write (*,*) j,b(:,j)
end do
end |
|
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 270
|
Posted: Sun Apr 30, 2023 8:06 pm Post subject: |
|
|
That would be interesting - if b were already allocated but got resized at the "not sure what happens here" line, that could result in some very difficult to track problems. |
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 270
|
Posted: Mon May 01, 2023 6:08 pm Post subject: |
|
|
Here is an attempt to isolate the problem with the shape of an array being reassigned.
Code: | Module m1
Implicit None
Real, Dimension(:,:), Allocatable, Public :: b
Real, Dimension(:,:,:), Allocatable, Public :: a
End Module m1
Module m2
!
Contains
!
Subroutine s1 ( )
Use m1, Only: a, b
!
Call s2 ( )
a = 1.0
Print *, shape(a)
Print *, shape(b)
b(:,:) = a(:,:,1)
Print *, shape(b)
!
Return
End Subroutine s1
!
!
Subroutine s2 ( )
Use m1, Only: a, b
!
Allocate ( a(35,30,1) )
Allocate ( b(35,30) )
!
Return
End Subroutine s2
End Module m2 |
It seems that the modules and main program may each need to be in a separate file:
Code: | Program p
Use m2, Only: s1
Call s1 ()
End Program p
|
But I am not entirely sure, because I do not get consistent results. If I keep everything in separate files, recompile and run, I get different outcomes. So far I have had the following outcomes:
1. A run-time crash after the second print statement
2. The program completes with no crash but the third print returns 1 30
3. The third print returns 1 30 but a run-time error is issued
... but now that I have submitted this example, if I compile and run from a command prompt, it seems to work ok! But building it within a Plato project creates the error. I really hope somebody at Silverfrost can reproduce and diagnose the error. I can try to forward a simple package containing the relevant files and settings if that would be helpful. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
Posted: Tue May 02, 2023 11:39 am Post subject: |
|
|
This appears to expose a bug in FTN95. A work-around is to have just one USE statement in module m2. Note that statements like "b(:,:) = a(:,:,1)" might be very expensive. There could be a lot of work going on to evaluate the addresses for each copy.
Code: | Module m1
Implicit None
Real, Dimension(:,:), Allocatable, Public :: b
Real, Dimension(:,:,:), Allocatable, Public :: a
End Module m1
Module m2
Use m1, Only: a, b
!
Contains
!
Subroutine s1 ( )
!
Call s2 ( )
a = 1.0
Print *, shape(a)
Print *, shape(b)
b(:,:) = a(:,:,1)
Print *, shape(b)
!
Return
End Subroutine s1
!
!
Subroutine s2 ( )
!
Allocate ( a(35,30,1) )
Allocate ( b(35,30) )
!
Return
End Subroutine s2
End Module m2
program maim
use m2
call s1()
end program maim |
|
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 270
|
Posted: Tue May 02, 2023 2:30 pm Post subject: |
|
|
Thanks Paul. I'm relieved you were able to isolate the bug. It has taken a great deal of work to locate the problem and then produce the small example.
Are you able to be more generic about what we should avoid until this problem is resolved? I am concerned that this problem may be occurring elsewhere in my program undetected. Should we be avoiding a USE statement in more than one subroutine or function within a module, and if so, is that only for arrays? For arrays of more than one dimension? Only for arrays that are assigned values?
What would you suggest in place of the expensive line? Simply removing the brackets on the left? A DO CONCURRENT? I had programmed this section in that way specifically because I thought it permitted the most efficient code. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
Posted: Tue May 02, 2023 7:50 pm Post subject: |
|
|
Simon
I need to investigate this issue before I can give a clear reply. At the moment I am not sure that this exposes a bug in FTN95.
Since sub1 and sub2 share the same arrays A and B, it seems natural to me to USE (i.e. load) the module just once in the header rather than separately in each subprogram.
At the moment I am guessing that FTN95 is producing separate instances of A and B when when USE appears in both subroutines and that this is probably wrong according to the Standard. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|