|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
sparge
Joined: 11 Apr 2005 Posts: 371
|
Posted: Thu Jun 09, 2011 10:14 am Post subject: An unexpected single step exception has occurred |
|
|
Has anyone ever seen this runtime error before? I haven't, and I have just started to get it this morning, with the /RELEASE build, after adding some code to a previously working app.
At the moment I can get no handle on the cause, because the /CHECKMATE and /DEBUG builds both fall over with an unknown access violation and display of assembler code. I only ran the /RELEASE build in desperation!
So, unusually, the /RELEASE build is "less unhelpful" than the other two builds. I confess I am baffled as to why a /RELEASE build should be single stepping in the first place, unless it is using a different meaning of single stepping to the usual one i.e. just going about its normal sequential instruction business without supervision |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Thu Jun 09, 2011 11:30 am Post subject: |
|
|
If you compile with /debug then run with sdbg, do you at least get a trace back ? |
|
Back to top |
|
|
sparge
Joined: 11 Apr 2005 Posts: 371
|
Posted: Thu Jun 09, 2011 11:58 am Post subject: |
|
|
Ho John,
No, I don't. I was running from within Plato before, but the same thing happens if SDBG is explicitly in control of the /DEBUG build. Just a window of assembler.
However, I have now found the line of offensive code. I'm still trying to figure out in a model applet how I managed to sneak it past the compiler. The best I can offer at the moment is this:
Code: |
program strung_out
use knots
character (len = nb) chintz, chance
chintz = 'xyz'
chance = chaout (chintz) ! the error is (mis)diagnosed here
stop
end program strung_out
module knots
integer, parameter :: nb = 3
contains
character (len = nb) function chaout (chainp)
character (len = nb) chainp
integer b, inp (nb)
do b = 1, nb
inp (b) = ichar (chainp (b)) ! the error is here
end do
chaout = char (inp (2)) // char (inp (3)) // char (inp (1))
end function chaout
end module knots
|
which causes FTN95 to identify a problem but misdiagnose both its location and nature:
strung_out.F95(5) : error 327 - In the INTERFACE to CHAOUT (from MODULE KNOTS), the first dummy argument (CHAINP) was of type CHARACTER(LEN=3) FUNCTION, whereas the actual argument is of type CHARACTER(LEN=3)
It is failing to pick up the fundamental syntax error that chainp (b) should be chainp (b: b), even though chainp is explicitly typed only three lines previously in the same function!
This misdiagnosis is clearly at the root of the original problem. I'm sure a little more wrapping should allow me to reproduce it. Watch this space
Andy |
|
Back to top |
|
|
sparge
Joined: 11 Apr 2005 Posts: 371
|
Posted: Thu Jun 09, 2011 2:26 pm Post subject: It's a wrap |
|
|
Right, time to declare "victory", spent too long on reproducing this already.
The following code snippet sneaks the fundamental syntax error past FTN95
Code: |
program strung_out
use knots
character (len = nb) chintz, chance
chintz = 'xyz'
call charcoal (chance, chintz)
stop
end program strung_out
module knots
integer, parameter :: nb = 3
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)) ! the error is here
end do
chaout = char (inp (2)) // char (inp (3)) // char (inp (1))
end function chaout
end module knots
|
The resulting /CHECKMATE and /DEBUG builds reproduce the runtime problem as originally reported. The /RELEASE build behaves a little differently, reporting as follows:
Access Violation
The instruction at address 20202020 attempted to read from location 20202020
20202020 routine at address 20202020 [+0000]
00401000 KNOTS!CHARCOAL [+001e]
004010d0 MAIN [+003c]
eax=0360fc02 ebx=00003a49 ecx=0360fc97
edx=000000fe esi=00402010 edi=0360fd28
ebp=0360fca8 esp=0360fc4c IOPL=0
ds=0023 es=0023 fs=003b
gs=0000 cs=001b ss=0023
flgs=00010a03 [CA OP NZ SN DN OV]
NB1 if subroutine charcoal is listed after function chaout rather than before, all three builds misdiagnose the nature and location of the error in the same way as the previous code snippet. The order has to be as per the code above, to fool the compiler.
NB2 if chintz and chance are declared in module knots rather than program strung_out, the runtime behaviour is slightly different:
- /CHECKMATE and /DEBUG builds display source code instead of assembler, and /DEBUG build reports privileged instruction rather than access violation
- /RELEASE build reports access violation a little differently:
Access Violation
The instruction at address 00404018 attempted to write to location 00003a49
00404018 routine at address 404018 [+0000]
00401000 KNOTS!CHARCOAL [+001e]
004010d0 MAIN [+0048]
eax=0360fca9 ebx=00003a49 ecx=0360fca0
edx=000000fe esi=00402010 edi=0360fd28
ebp=0360fcb0 esp=0360fc54 IOPL=3
ds=0023 es=0023 fs=003b
gs=0000 cs=001b ss=0023
flgs=00010a13 [CA OP NZ SN DN OV]
04040ff outs
00404100 outsb
00404101 cmpb ah,[eax] |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Fri Jun 10, 2011 3:06 am Post subject: |
|
|
Andy,
I tried to compile your program and found what I think is a problem with your program and with modules, which has been discussed previously.
Your second line has "use knots", but the version of the knots module it will use will be the previous one compiled and not the one listed below. Later in your program, the module knots will be updated.
If you first use the command "del knots.mod" you will see the problem.
I would suggest that the module should be compiled (listed) before it is used, as I don't think FTN95 does address this issue.
I don't know if the standard requires the compiler to be able to cope with this.
You should try the following :
Code: | module knots
integer, parameter :: nb = 3
contains
character (len = nb) function chaout (chainp)
character (len = nb) chainp
integer b, inp (nb)
do b = 1, nb
inp (b) = ichar (chainp (b:b)) ! the error is here
end do
chaout = char (inp (2)) // char (inp (3)) // char (inp (1))
chaout = chainp(2:nb) // chainp(1:1) ! doesn't this do the same ??
end function chaout
end module knots
program strung_out
use knots
character (len = nb) chintz, chance
chintz = 'xyz'
chance = chaout (chintz) ! the error is (mis)diagnosed here
stop
end program strung_out
|
John |
|
Back to top |
|
|
sparge
Joined: 11 Apr 2005 Posts: 371
|
Posted: Fri Jun 10, 2011 10:10 am Post subject: |
|
|
Hi John,
Hmm, yes, this rings a bell. When I compile my code I always have main program and modules in separate files, and I rely on Plato to get the compilation order right - so this issue would not arise for me, and it is not the source of the problem I am reporting.
Andy |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Fri Jun 10, 2011 11:08 am Post subject: |
|
|
Andy,
I had to put the module first to get it to compile. Afterwards, I modified the code as follows:
Code: | module knots
integer, parameter :: nb = 3
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:b)) ! the error is here
end do
chaout = char (inp (2)) // char (inp (3)) // char (inp (1))
end function chaout
end module knots
program strung_out
use knots
character (len = nb) chintz, chance
chintz = 'xyz'
call charcoal (chance, chintz)
write(*,*) chance
stop
end program strung_out |
The main mod is in the line where you get an error (changed CHAINP(B) to CHAINP(B:B)). I didn't know that ICHAR was capable of operating on more than one char in a string at any one time (is it?), so I would automatically try to extract one char at a time. My WRITE statement tells me you get the right reorganisation if you do this. Using substring notation feeds ICHAR with only one character.
Eddie |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Fri Jun 10, 2011 11:56 am Post subject: |
|
|
I suggested two alternative changes:
do b = 1, nb
inp (b) = ichar (chainp (b:b)) ! the error is here
end do
chaout = char (inp (2)) // char (inp (3)) // char (inp (1))
or
chaout = chainp(2:nb) // chainp(1:1) ! doesn't this do the same ??
I think both address the problem you had. |
|
Back to top |
|
|
sparge
Joined: 11 Apr 2005 Posts: 371
|
Posted: Fri Jun 10, 2011 12:52 pm Post subject: |
|
|
Eddie (edit: and John, who snuck in while I was composing this),
Evidently I did not make my point(s) clear.
The code I posted is designed to reproduce a FTN95 compile-time oversight and associated bad run-time behaviour.
Point 1: Compile-time oversight. The line of source with the comment "! the error is here", and which you corrected, is a basic error of syntax that FTN95 is not picking up. It is meant to be there! In my original code, it was committed by me, in haste. The resulting executable code, which should not have been produced by the compiler, (not surprisingly) failed at runtime, and not gracefully.
Point 2: Bad run-time behaviour. The /DEBUG and /CHECKMATE executable code that FTN95 generates fails at runtime with access violation and without diagnosis or traceback. In both cases, these builds are less helpful than the /RELEASE build - not Silverfrost's design intention for these builds.
The compile order issue is a red herring - although I do find it disturbing that a given compiler can generate different executable outputs from a given portion of source code, depending on how the source code is packaged. Before we had modules, I used to have every subroutine and function in a separate file. Now we have modules, I always keep the main program and every module in a separate file. It is the only way that makes sense to me. I'm going to have to make that clear when posting code in future, with multiple uses of "code" tags.
Andy |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Fri Jun 10, 2011 2:46 pm Post subject: |
|
|
Andy,
I assumed that you knew a syntax that I didn't! Agreed, if it isn't valid, then the compiler should pick it up, and also agreed, that you should get more help if you go for error-checking than if you leave it out.
It isn't even that the issue is with the Fortran-95 or -90 part of the code, it is something that has been there from Fortran-77, and agreed, it needs looking at. I had a go at removing the MODULE stuff, and the error isn't picked up even if you modify your example to look like Fortran-77.
Prior to MODULEs, every routine was self-contained and could be compiled stand-alone (EXTERNAL resolves the one ambiguity regarding whether or not a symbolic name was a FUNCTION when used as a subprogram argument - it is evident from context in an assignment statement that it is either an undeclared array or a function, and that is resolvable during linking). With MODULE and USE, one may need the contents of a module to do a compilation, which I suppose is the reason for those MOD files, as the source code could be named anything, and finding it could be difficult.
This is a degree of complexity that I had not thought about before. Not having the MODULE to hand is like (in a Fortran-77 context) not finding an INCLUDE file, and everything may not be resolvable at link time as it used to be.
Eddie |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Sat Jun 11, 2011 1:02 am Post subject: |
|
|
Andy,
My apologies. I now see the problem you have identified.
Certainly the error does not report where the syntax problem is.
I did look at the cryptic error report and tried to find how CHAINP could be interpreted as a function.
I must admit I don't understand the need for CONTAINS and put the interpretation of "ichar (chainp(b))" as valid/possible function reference to this.
Is the code, as you wrote, inside MODULE and CONTAINS possible ? It isn't what you wanted but I don't know if it is illegal.
My attempt in a dos box with /check /lgo did not proceed to link and run to test SDBG.
There is a lot of new syntax in fortran now, with .net, 2003 and 2008. You should look at the 2003 or 2008 standard. Most of it I don't understand and I think all of it I don't need !
My sympathies are with the compiler writers.
John |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Sat Jun 11, 2011 7:00 am Post subject: Re: |
|
|
Code: |
program strung_out
use knots
character (len = nb) chintz, chance
chintz = 'xyz'
chance = chaout (chintz) ! the error is (mis)diagnosed here
stop
end program strung_out
module knots
integer, parameter :: nb = 3
contains
character (len = nb) function chaout (chainp)
character (len = nb) chainp
integer b, inp (nb)
do b = 1, nb
inp (b) = ichar (chainp (b)) ! the error is here
end do
chaout = char (inp (2)) // char (inp (3)) // char (inp (1))
end function chaout
end module knots
|
Actually, your function chaout is perfectly valid Fortran if chainp is an EXTERNAL function of type character(len=nb). The compiler treats it this way. The error then is that you don't pass a function to it but a character(len=nb) variable in your main program.
The compiler diagnosis is correct I think.
So, either change the main program to pass a function (declared EXTERNAL) or change chainp(b) to chainp(b:b).
Incidently, you DO need to move the module so it is first in the file. As it is, the compiler will compile your main program first and read the interface definition from the MOD file it created at the last compile. Your first compile will always fail, as will subsequent compiles that follow a change to the interface.
This is what JohnCampbell was saying I think.
Obviously, if you're using Plato and separate files for your main program and module you will be fine as Plato will determine the correct compilation order. |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Sat Jun 11, 2011 8:25 am Post subject: |
|
|
chainp was not declared EXTERNAL, so should the compiler assume this?
Also, "if you're using Plato and separate files for your main program and module you will be fine as Plato will determine the correct compilation order." Can this be assumed ? |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Sat Jun 11, 2011 10:40 pm Post subject: Re: |
|
|
JohnCampbell wrote: | chainp was not declared EXTERNAL, so should the compiler assume this?
|
The compiler should assume this. You only need an EXTERNAL statement if the function name is the same as an INTRINSIC function ("Fortran 95/2003 Explained", p. 82), or if the function is passed as an actual argument to a subroutine or function. (Its a dummy argument in the example, and EXTERNAL is not needed for those). These are the rules for FORTRAN 77, which Fortran 95 inherits.
JohnCampbell wrote: |
Also, "if you're using Plato and separate files for your main program and module you will be fine as Plato will determine the correct compilation order." Can this be assumed ? |
Plato parses the file collection in a project and determines the correct compile order. I assume it uses Automake.exe to do this, as this utility is included in Plato's install directory. |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Sun Jun 12, 2011 2:06 am Post subject: |
|
|
davidb,
I'm not sure that the default assumption is a function, as a text I have, "Fortran 95 Handbook", by Adams et al, claims "the processor assumes that the argument is a variable".
I'd expect that for "chainp" to be assumed a function, it should have been declared EXTERNAL, although the only valid interpretation of "chainp(b)" is that it is a function.
You say "The compiler should assume this", but I'm not sure that this is the case. My recollection of F77, is that EXTERNAL is required and not optional, but alas I've recently lost my copy of the Fortran 77 standard.
I also think the argument for the intrinsic "char" can not be character*3.
While we are discussing the subtleties of EXTERNAL, has anyone looked at the proposed 2008 standard ? The amount of new code structures in it is really scary. I wonder how many would use this new language. To me it looks like a lead weight that will kill the language. Who could afford to develop a compiler to support this ? I wonder how many Fortran users have given input to this latest colossus.
John |
|
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
|