View previous topic :: View next topic |
Author |
Message |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Sat Sep 22, 2018 2:19 pm Post subject: Failure to detect error in source code |
|
|
The program below contains one error: line-22 has chainp(b) instead of chainp(b:b). The bug is not difficult to diagnose at compile time, as Gfortran and NAG do.
FTN95 /64 /checkmate produces an EXE that crashes with an access violation when run. FTN95 /checkmate produces a 32-bit EXE that crashes with "Attempt to execute privileged instruction". FTN95 /opt leads to "...attempted to write to location 00000001". In other words, the bug is not caught at compile or run time, even with /checkmate.
The test program is a modification of an earlier submission by user "Sparge" in 2011, see http://forums.silverfrost.com/viewtopic.php?t=1967&highlight=attempted+access+location .
Code: | program strung_out
implicit none
integer, parameter :: nb = 3
character (len = nb) chintz, chance
chintz = 'xyz'
call charcoal (chance, chintz)
print *,chance
stop
contains
subroutine charcoal (champ, chimp)
character (len = nb) champ, chimp
champ = chaout (chimp)
end subroutine charcoal
character (len = nb) function chaout (chainp)
character (len = nb) chainp
integer b, inp (nb)
do b = 1, nb
inp (b) = ichar (chainp (b)) ! ***ERROR***
! inp (b) = ichar (chainp (b:b)) ! ***CORRECT***
end do
chaout = char (inp (2)) // char (inp (3)) // char (inp (1))
end function chaout
end program strung_out |
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Sun Sep 23, 2018 6:39 am Post subject: |
|
|
Thank you for the feedback. I will make a note of this. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Thu Sep 27, 2018 2:17 pm Post subject: |
|
|
I have had a look at this and the basic problem is that chaout is called before it has been defined. So without multiple passes through the code, the compiler thinks that chainp could be a function returning a character variable. Maybe the compiler ought to be using multiple passes at this point - I would have to look that up.
As it is, in this context FTN95 requires the order of the CONTAINed subprograms to be changed (so that chaout is called after it has been defined) before you get a clear error report at compile time. With the given order, you are only alerted to an error when you get an access violation at run time. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Thu Sep 27, 2018 3:18 pm Post subject: |
|
|
One of the great advantages of having several compilers available for use is that the same source code can be run through each to find problems picked up by one that another misses. |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Thu Sep 27, 2018 3:51 pm Post subject: Re: |
|
|
PaulLaidler wrote: | I have had a look at this and the basic problem is that chaout is called before it has been defined. So without multiple passes through the code, the compiler thinks that chainp could be a function returning a character variable. Maybe the compiler ought to be using multiple passes at this point - I would have to look that up. |
Section 12.3.2 of the Fortran 95 Standard contains this note:
Quote: | NOTE 12.3
An interface block cannot be used to describe the interface of an internal procedure, a module procedure, or an intrinsic procedure because the interfaces of such procedures are already explicit. |
CHAOUT and CHARCOAL are internal procedures contained in the same module. The compiler has to make at least two passes when it compiles modules with contained procedures, although in the first pass it only needs to do just enough to gather the correct interfaces. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Thu Sep 27, 2018 5:02 pm Post subject: |
|
|
mecej4
I think that you are probably right. I know that FTN95 does do multiply passes but apparently not adequately in this context.
Until we can get this fixed it will be necessary to make it easier for the compiler by using the ordering that does not need the double pass. To me this is more natural to define a thing before it is used. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Thu Sep 27, 2018 10:13 pm Post subject: |
|
|
Suppose then that the order of the two functions is reversed. What effect does that have:
Quote: | program strung_out
implicit none
integer, parameter :: nb = 3
character (len = nb) chintz, chance
chintz = 'xyz'
call charcoal (chance, chintz)
print *,chance
stop
contains
character (len = nb) function chaout (chainp)
character (len = nb) chainp
integer b, inp (nb)
do b = 1, nb
inp (b) = ichar (chainp (b)) ! ***ERROR***
! inp (b) = ichar (chainp (b:b)) ! ***CORRECT***
end do
chaout = char (inp (2)) // char (inp (3)) // char (inp (1))
end function chaout
subroutine charcoal (champ, chimp)
character (len = nb) champ, chimp
champ = chaout (chimp)
end subroutine charcoal
end program strung_out |
What then? Even stranger, although the error occurs during compilation:
Quote: | [FTN95/Win32 Ver. 8.30.0 Copyright (c) Silverfrost Ltd 1993-2018]
NO ERRORS [<CHAOUT> FTN95 v8.30.0]
0025) champ = chaout (chimp)
*** In the INTERFACE to CHAOUT, the first dummy argument (CHAINP) was of type
CHARACTER(LEN=3) FUNCTION, whereas the actual argument is of type
CHARACTER(LEN=3)
1 ERROR [<CHARCOAL> FTN95 v8.30.0]
NO ERRORS [<STRUNG_OUT> FTN95 v8.30.0]
*** Compilation failed |
What's that about CHAINP being a FUNCTION? |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Wed Oct 10, 2018 12:43 pm Post subject: |
|
|
Sorry, Eddie, until now I had overlooked your example with the subroutines rearranged. In this case, however, what the compiler says is proper, although it may be a bit difficult to understand what (and why) it said. Given your code, Gfortran says
Code: | spargeddie.f90:25:16:
champ = chaout (chimp)
1
Error: Expected a procedure for argument 'chainp' at (1) |
The explanation is as follows.
Let us look at the code of FUNCTION CHAOUT, which is a contained procedure and, therefore, has an explicit interface available across the entire program. The argument, "chainp", is declared as a scalar character variable (of length nb). When the compiler sees "chainp(b)", it has to recognise that as a function reference. What is given within the parentheses is not a valid substring index pair. Therefore, it must be an argument list with one member.
Note that the type of the dummy argument is detected only after the executable statement inside the DO loop is parsed. This feature is part of our legacy from Fortran 77 and earlier.
My complaint, then, is that the compiler should have given the same error even when the block of code for function CHAOUT was placed earlier (or elsewhere) in the source file. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Wed Oct 10, 2018 2:58 pm Post subject: |
|
|
Hi Mecej4,
It was really in response to Paul about the order.
This sort of coding lies far outside my personal safe subset of Fortran.
Thanks for the explanation.
Eddie |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Wed Jul 17, 2019 7:39 am Post subject: |
|
|
This has now been fixed for the next release of FTN95. FTN95 will provide the correct error report at compile time. |
|
Back to top |
|
|
|