|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Sat Feb 16, 2013 10:06 pm Post subject: Bug with pointer components of derived type. |
|
|
The following code contains a derive type PER_T which contains a pointer to an array of derived type GRP_T.
The derived type GRP_T in turn contains a pointer to an array of derived type EL_T.
When the line marked (A) is executed, the members of pers(1) lose their values and are set to zero. The allocate on this line is not working; this is indicated by the pointer in line (B) which becomes NULL.
I have tracked this down to be due to the use of null() to initialise the els(:) pointer in line (C). If I remove this initialisation, the code works correctly.
Please can this be fixed?
Regards
David
Code: |
program anon
type el_t
real :: a
end type el_t
type grp_t
type(el_t), pointer :: els(:) => null() ! (C)
end type grp_t
type per_t
integer :: num
real :: x
type(grp_t), pointer :: grps(:) => null()
end type per_t
type(per_t), allocatable :: pers(:)
integer :: i
type(grp_t), pointer :: grps_ptr(:)
allocate (pers(1))
! Setup values of pers(1)
pers(1)%num = 1
pers(1)%x = 1.0
! Allocate grps(:) part of pers(1) to point to array of size 5
allocate(pers(1)%grps(5)) !< (A) BUG HERE. Value of pers(1)%num and pers(1)%x get changed to 0
grps_ptr => pers(1)%grps(:) !< (B) BUG HERE. grps_ptr is NULL POINTER and shouldn't be
! Allocate els(:) to point to array of size 1
do i=1, 5
allocate (pers(1)%grps(i)%els(1))
end do
! Set value of a in els
pers(1)%grps(1)%els(1)%a = 2.0
print *, pers(1)%num
print *, pers(1)%x
end program anon
|
_________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Last edited by davidb on Sun Feb 17, 2013 9:08 pm; edited 1 time in total |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7929 Location: Salford, UK
|
Posted: Sun Feb 17, 2013 9:20 am Post subject: |
|
|
Thanks. I have logged this for investigation. |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Wed Jul 31, 2013 8:10 am Post subject: |
|
|
This is still an issue with 6.35. I wonder if it could be patched for the next release please.
I have produced the following very simple example to show what is wrong. When the second allocate is done, the data at the address of per(1) is initialized instead of the data at address of grps(1) (corrupting the value of num).
The error is also obvious from the EXPLIST for this code.
Code: |
program anon
type grp_t
integer :: n = 2 ! (C)
end type grp_t
type per_t
integer :: num
type(grp_t), pointer :: grps(:) => null()
end type per_t
type(per_t), allocatable :: pers(:)
! Setup values of pers(1)
allocate (pers(1))
pers(1)%num = 1
! BUG HERE. Allocate needs to set n = 2 to initialise grps(1).
! However the data at the address of pers(1) is initialised instead.
! This causes the value of pers(1)%num to change to 2
! Allocate grps(:) part of pers(1) to point to array of size 1
allocate(pers(1)%grps(1))
print *, pers(1)%num, ' <-- should be 1 !'
end program anon
|
_________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7929 Location: Salford, UK
|
Posted: Fri Aug 02, 2013 7:47 pm Post subject: |
|
|
I did do a preliminary investigation on this bug, sufficient to indicate that it is a reality nasty one to fix.
Given that a new release is planned shortly, it is unlikely that this one can be fixed in time. |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Fri Aug 02, 2013 8:12 pm Post subject: |
|
|
If you can get the front end of the compiler to replace
Code: |
allocate(pers(1)%grps(1))
|
by
Code: |
p => pers(1)
allocate(p%grps(1))
|
the BUG will disappear.
I can do this in Fortran code, but have to declare pers with the TARGET attribute, which I don't really need.
I am surprised this is so tricky. Looks like just an address is wrong looking at the assembly. _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7929 Location: Salford, UK
|
Posted: Fri Aug 02, 2013 8:28 pm Post subject: |
|
|
Thanks for the suggestion. |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Sat Apr 12, 2014 2:05 pm Post subject: |
|
|
Paul,
Was this bug fixed as a side-effect of the recent fix to default initialisation in the next release, or is it still an ongoing issue. _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7929 Location: Salford, UK
|
Posted: Mon Apr 14, 2014 7:49 am Post subject: |
|
|
Unfortunately this issue is still outstanding. |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Sat Apr 26, 2014 10:27 am Post subject: |
|
|
I have been studying this some more and have found the problem (at least at the assembly level).
I looked at the following codes, which are the simplest I can make which reproduces the problem.
Code P1 shows the BUG and doesn't work, while P2 works fine. The only difference is that the integer x is located at the start of bbb in code P1, whereas in P2 the pointer array is at the beginning.
Code: |
! Doesn't work
program P1
type aaa_t
integer :: a = 999
end type aaa_t
type bbb_t
integer :: x
type(aaa_t), pointer :: aaa(:)
end type bbb_t
type(bbb_t) :: bbb(1)
! Setup bbb(1)
bbb(1)%x = 1
! Allocate aaa(:) part of bbb(1) to point to array of size 5
allocate(bbb(1)%aaa(5))
print *, bbb(1)%x, ' <= should be 1 but 999 is printed!'
end program P1
|
Code: |
! Works
program P2
type aaa_t
integer :: a = 999
end type aaa_t
type bbb_t
type(aaa_t), pointer :: aaa(:)
integer :: x
end type bbb_t
type(bbb_t) :: bbb(1)
! Setup bbb(1)
bbb(1)%x = 1
! Allocate aaa(:) part of bbb(1) to point to array of size 5
allocate(bbb(1)%aaa(5))
print *, bbb(1)%x, ' <= should be 1 and is!'
end program P2
|
The assembly code for P1 and P2 include the following loop for doing the default initialisation (its the same assembly code in each case):
Code: |
00000090(42/3/458) Label __N3
00000090(43/6/492) mov ecx,II@01
00000093(44/6/492) imul ecx,=28
00000099(45/4/289) mov edx,AAA_T(999)
0000009f(46/4/289) mov BBB[ecx],edx
000000a3(47/4/467) inc II@01
000000a6(48/4/468) mov eax,LoopUpper@1
000000a9(49/4/468) cmp eax,II@01
000000ac(50/4/468) jge __N3
|
II@01 is the loop counter which starts at 0 and LoopUpper@1 is upper value of the loop counter, 4.
In this code register ecx used in BBB[ecx] contains the successive values 0, 28, 56, etc. This is correct for P2. However it isn't correct for P1 where it needs to contain the values 4, 32, 60, etc.
You could possibly fix this by adding the appropriate offset to ecx as follows.
Code: |
00000090(43/6/492) mov ecx,II@01
00000093(44/6/492) imul ecx,=28
add ecx, 4
|
Obviously the offset to be added will change depending on where in BBB the pointer array is located. In code P2 for example, the offset would be zero (which explains why the BUG doesn't get exposed in this case).
PS. I also looked at the equivalent of P1 but with a scalar for BBB instead of an array of size 1; this code works and has the offset that is needed.
Code: |
00000090(42/3/267) Label __N3
00000090(43/6/278) mov ecx,BBB[8]
00000093(44/6/278) add ecx,II@01
00000096(45/5/280) mov edi,BBB[4]
00000099(46/4/159) mov eax,AAA_T(999)
0000009f(47/4/159) mov [edi+ecx*4],eax
000000a3(48/4/274) inc II@01
000000a6(49/4/275) mov ecx,LoopUpper@1
000000a9(50/4/275) cmp ecx,II@01
000000ac(51/4/275) jge __N3
|
I hope this helps _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7929 Location: Salford, UK
|
Posted: Sat Apr 26, 2014 4:04 pm Post subject: |
|
|
Thanks for this. I will make a note of your analysis.
However, this needs to be fixed in the tree structure before we get to the backend assembly. That way the fix is applied to both Win32 and .NET and potentially Win64. The backend will handle it once the tree is fixed. |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Sat Apr 26, 2014 6:05 pm Post subject: |
|
|
Yes, it needs fixing in the front end.
As FTN95 doesn't expose the abstract tree I haven't been able to look at it.
But hopefully having this little look at the assembly code for Win32 may provide some insight into what may be going on. You at least know that an incorrect memory offset is the cause. You might also look at the difference between the abstract tree for the cases where BBB is an array (which fails) and where BBB is a scalar (which works).
Good luck and thanks for looking Paul. Default initialisation does seem to be a big feature in my coding at present (like a habit), and I am having to do explicit initialisation as a workaround with FTN95. _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Sat Apr 26, 2014 6:09 pm Post subject: Re: |
|
|
PaulLaidler wrote: | and potentially Win64.
|
Are you teasing us? _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2822 Location: South Pole, Antarctica
|
Posted: Sun Apr 27, 2014 6:48 am Post subject: |
|
|
Wow...64bit... please don't say NO, Paul |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7929 Location: Salford, UK
|
Posted: Mon Jun 24, 2019 10:47 am Post subject: |
|
|
This issue has finally been fixed. The fix will be in the next release of FTN95. |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Sun Jul 07, 2019 6:05 pm Post subject: |
|
|
Thanks Paul, your work on this is much appreciated. _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
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
|