![forums.silverfrost.com Forum Index](templates/subSilver/images/logo_phpBB.gif) |
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Tue Aug 24, 2021 1:13 am Post subject: Unexpected subscript out of bounds error |
|
|
Many old Fortran 77 programs declare a large workspace array in the main program and hand off segments of that array to subroutines as arguments. The actual argument for each such workspace array segment appears to be an array element, but the corresponding dummy variable in the called subroutine is an array of 1, 2, etc. dimensions. The Fortran 95 standard provides for this in section 12.4.1.4 "Sequence Association", in which the third sentence of the first paragraph says: If the actual argument is an array element designator, the element sequence consists of that array element and each element that follows it in array element order.
It is not clear to me what rules are followed by FTN95 when such a program is compiled and run with /check. Here is a test program which runs without error when compiled and run with other compilers with those compilers' subscript checking options turned on, but aborts when compiled and run with FTN95 /check.
Code: | program subbug
implicit none
integer, parameter :: ndim=20, nrp1=11
integer iwksp(100), i, j
!
do i=1,ndim; do j=1,5
iwksp((j-1)*ndim+i) = 10*i+j
end do; end do
call vaddp(ndim, iwksp(ndim+nrp1))
end program
subroutine vaddp(ndimi, ja)
implicit none
integer ndimi, ja(ndimi,*)
!
print *, ja(1,4)
return
end subroutine |
When compiled with /check and run inside SDBG up to line 16, the array JA is displayed as having dimensions (20,3). My question is regarding the second upper bound of 3, which is more restrictive than what is allowed by the sequence association rule that I quoted above.
The first column of JA corresponds to WKSP(31:50), the second column of JA to WKSP(51:70), the third column of JA to WKSP(71:90), and JA(1:10, 4) to WKSP(91:100). References to JA(i,4) with i > 10 would be out of bounds, but using JA(1,4) should not cause an error, it seems to me.
The test program as well as the larger program from which it was derived work fine when neither /check nor /undef is specified when compiling. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Tue Aug 24, 2021 4:37 am Post subject: |
|
|
This appears to be a possible change to FTN95 / SDBG ?
In the past, I have been very impressed with FTN95 in that when performing
"call vaddp(ndim, iwksp(ndim+nrp1))"
which is effectively
"call vaddp(ndim, iwksp(31))"
it effectively identifies in vaddp that "ja" has a size of 70 integers, even though it declares "integer ja(20,*) .
This can even go through multiple calls, which has impressed me !
I have seen this in other programs using this "F77 wrapper approach"
What appears to be new is that FTN95 is now calculating the second dimension of ja is limited to 3, based on the available declared size of iwksp.
My guess is that previously "ja(10,4)" would have been ok but "ja(11,4)" would have been "Array subscript out of bounds".
Ie, it appears to be doing a subscript range test, rather than a defined memory range test.
Now, FTN95 is limiting the second dimension of ja to 3. Applying the dimension limit, rather than the memory address limit looks to be a change.
No surprise that turning off /check or /undef removes the diagnostic error.
I do find that the most common form of "Array subscript out of bounds" with old code is when one of the subscripts is zero.
SDBG finds most of these. Checking subscript ranges, rather than memory range is a better test, although not in this particular case.
My interpretation, but perhaps wrong ?
It would be good to know which version of FTN95 / SDBG / SDBG64 has this change ( if this is the change that happened?)
The following demonstrates my assumption. Code: | program subbug
implicit none
integer, parameter :: ndim=20, nrp1=11
integer iwksp(100), i, j
!
do i=1,ndim; do j=1,5
iwksp((j-1)*ndim+i) = 10*i+j
end do; end do
call vadp (ndim, iwksp(ndim+nrp1))
call vaddp (ndim, iwksp(ndim+nrp1))
end program
subroutine vaddp(ndimi, ja)
implicit none
integer ndimi, ja(ndimi,*)
!
print *, ja(1,4)
return
end subroutine
subroutine vadp (ndimi, ja)
implicit none
integer ndimi, ja(*), k
!
do k = 69,71
print *, k, ja(k)
end do
return
end subroutine |
Note in subroutine vadp, using SDBG ja is identified as ja(70). When was this capability introduced to SDBG ? |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Tue Aug 24, 2021 12:39 pm Post subject: |
|
|
Thanks for your comments, John. I see that, depending on the circumstances and the nature of the code being checked, checking for either or both of the following is what the programmer may wish for:
1. Checking that only memory within the bounds of the actual argument, ignoring the bounds specified for the dummy argument in each extent.
2. Checking that each subscript of the array reference is within the bounds specified for the dummy argument.
The first option is useful if the subprogram is reliable and the programmer wishes to check if the workspace being given to it is sufficient. The second option is useful if the subprogram itself is to be checked for proper multidimensional array usage.
One can think of situations where multiple sections of the workspace array are passed as arguments, and may be passed along down the chain to a subprogram where aliasing can occur between a pair of such sections. Such errors could be quite difficult to detect.
However, we did not have assumed shape arguments available to us in Fortran 77, and when the dummy argument is declared to be of assumed size (with ja(ndimi,*)), the first option seems to be more appropriate.
The oldest version of FTN95 that I have on my current PC is 7.20. It behaves the same as the current version, and in it SDBG reports the size of the dummy argument JA as (20,3). |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Wed Aug 25, 2021 3:04 am Post subject: |
|
|
The error report is probably a good option. If you wanted ja(20,4) available, then iwksp(110) would be a more robust approach. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Thu Aug 26, 2021 7:29 am Post subject: |
|
|
mecej4
Thanks for this report. i hope to be able to take a look at it next week. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Thu Aug 26, 2021 4:40 pm Post subject: Re: |
|
|
JohnCampbell wrote: | The error report is probably a good option. If you wanted ja(20,4) available, then iwksp(110) would be a more robust approach. |
Perhaps it would have made things easier if the original F77 program declared the shared workspace array as one-dimensional and the actual arguments for not-yet-used workspaces were also one-dimensional, and the called subroutines then declared the dummy arguments as two or higher dimensional arrays that suited the algorithms implemented in each subroutine. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Fri Aug 27, 2021 7:20 am Post subject: |
|
|
Mecej4,
Not sure I agree with your summary. A more robust approach should be a larger working array.
The main program should declare the workspace "iwksp(100)" of sufficient size for all the calls.
However subroutine vaddp uses a 2d array ja(ndimi,*). If it was declared as ja(ndimi,4), we could say there is a problem as the workspace is too small to provide that array.
What if you used "print *, ja(ndimi,4)" ?
What FTN95 does to check the calls, does assist in validating this approach.
It is interesting that you state "The Fortran 95 standard provides for this in section 12.4.1.4 "Sequence Association" ", as this approach is often described as illegal old stype FORTRAN, especially if there are mixed types such as using a real*8 workspace for an integer array.
Prior to FTN95, I wrote my own routine "MEM_ALLOC" (with FTN77) which managed the workspace address for subroutines and checked the available space, as well as managing the release of arrays at the end of their use, like ALLOCATE and DEALLOCATE. It also had the feature of returning an address and size of the largest available free space in the workspace array.
I also had EQUIVALENCE'd real*8 and integer*4 workspace arrays to try and minimise the mixed mode warnings that compilers provided. This required identifying the type of array (byte size) being used and provide the appropiate array pointer. I have been gradually removing it's use, although the function of "give me the biggest array available" is still not yet in Fortran.
Prior to 1990, this coding approach was essential for most large Fortran programs to function. For C (or PL/!) programmers to claim in this millenium that it was illegal Fortran and should be made an error dismisses much of the achievements of Fortran up to that time. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Mon Aug 30, 2021 1:04 pm Post subject: |
|
|
Mecej4
I have had an initial look at this and my first impression is that it may not be easy to fix.
When the rank of the actual argument is the same as the rank of the dummy argument, FTN95 is designed to check the bounds even for star-sized arrays.
But in this case the rank of the dummy argument is greater than that of the actual argument and FTN95 has not allowed for this case.
One possibility would be to get FTN95 to check that the ranks are the same and to abandon bounds checking when they are not. If the two ranks are currently accessible at runtime then it should be relatively easy to "fix" in this way. Otherwise some form of redesign or extension will be needed. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Mon Aug 30, 2021 1:33 pm Post subject: |
|
|
Paul,
Thanks for your assessment of the issue and your thoughts on what could be done.
I think that many Fortran compilers do no bounds checking at all for the last subscript of a multidimensional argument declared as (nn,mm,...,*). This is in keeping with the prohibition in the standard regarding using UBOUND on that last subscript.
FTN95 could provide an option which, if chosen by the user, suppresses bounds checking for such subscripts. Doing this would not even require comparing the ranks of the argument in the caller and callee. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Mon Aug 30, 2021 2:33 pm Post subject: |
|
|
I disagree that FTN95 needs fixing and certainly not by disabling this feature.
What it is doing is very useful. Few other compilers would report there is a problem using "print *, ja(1,4)" by carrying through the size of the declared available space in the source routine.
FTN95 is reporting a problem with ja(1,4), although the problem is from ja(11,4). It did get right that the (:,4) is not fully resourced, which in all but unusual conditions is a valid report.
Any fix should not remove this capability. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Mon Aug 30, 2021 5:04 pm Post subject: |
|
|
Bounds checking is enabled when using /CHECK and when using /BOUNDS_CHECK.
When using /CHECK, bounds checking can be disabled by adding /INHIBIT_CHECK 20 (this keeps other checks in place).
This disables all bounds checking, not just when the ranks are different. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Mon Aug 30, 2021 6:55 pm Post subject: |
|
|
Thanks for the information about /INHIBIT_CHECK 20.
The FTN95.CHM file included with 8.70 shows explanations of /INHIBIT_CHECK n for n = 1 to n = 14. What, if anything, do values of n from 15 to 19 signify?
Are there values of n > 20 that are currently recognised by the compiler? |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Tue Aug 31, 2021 7:38 am Post subject: |
|
|
Mecej4
The maximum value is currently 20 and that is the one to use in this context. I will check if the others are still active and see if I can document them in a meaningful way.
I could add item 21 in order to suppress bounds checking for star-sized arrays of rank greater than one. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Tue Aug 31, 2021 10:40 am Post subject: |
|
|
Paul,
The problems described in this thread would be alleviated if one could place pairs of the directives FTN95$OPTIONS(INHIBIT_CHECK 21) ..FTN95$OPTIONS(ENABLE_CHECK 21) in the bodies of the relevant subprograms. assuming that the second note of https://silverfrost.com/ftn95-help/directiv/comment_embedded_directives.aspx also applies to INHIBIT_CHECK and ENABLE_CHECK.
I asked about INHIBIT_CHECK n for n = 15 to n = 19 because I have not yet been able to see if FTN95 Version 8.80 has these values of n as newly added options.
Note to John Campbell:
Whether or not Paul implements /inhibit_check 21, FTN95 will continue to honor the options /check, /undef, etc., as it has done in the past. The "do no harm" principle will be satisfied. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Wed Sep 01, 2021 9:35 am Post subject: |
|
|
Here is a summary of the missing /INHIBIT_CHECK items...
15 - same as item 5 but only for module procedures
16 - spare
17 - suppress a recursion check (64 bit only)
18 - suppress argument alias checking (cancels /CHECK_ALIAS)
19 - suppress array conformance checking
20 - suppress array bounds checking (simple arrays, not array sections) |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|