forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Unexpected subscript out of bounds error
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Tue Aug 24, 2021 1:13 am    Post subject: Unexpected subscript out of bounds error Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Tue Aug 24, 2021 4:37 am    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Tue Aug 24, 2021 12:39 pm    Post subject: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Wed Aug 25, 2021 3:04 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7916
Location: Salford, UK

PostPosted: Thu Aug 26, 2021 7:29 am    Post subject: Reply with quote

mecej4

Thanks for this report. i hope to be able to take a look at it next week.
Back to top
View user's profile Send private message AIM Address
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Thu Aug 26, 2021 4:40 pm    Post subject: Re: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Fri Aug 27, 2021 7:20 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7916
Location: Salford, UK

PostPosted: Mon Aug 30, 2021 1:04 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Mon Aug 30, 2021 1:33 pm    Post subject: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Aug 30, 2021 2:33 pm    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7916
Location: Salford, UK

PostPosted: Mon Aug 30, 2021 5:04 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Mon Aug 30, 2021 6:55 pm    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7916
Location: Salford, UK

PostPosted: Tue Aug 31, 2021 7:38 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Tue Aug 31, 2021 10:40 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7916
Location: Salford, UK

PostPosted: Wed Sep 01, 2021 9:35 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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