Here is my first strong feeling about IMPLICIT NONE: It is not even one hundredth
as useful as a compiler that flags variables used before set.
And my second is: It is far from as convenient as those ``lists of variables used''
that we had on compile-time print-outs 20 years ago.
I do not deny any usefulness to IMPLICIT NONE, I am just much more enthousiastic
over some other verification methods. Hem, is that sufficient to avoid a flame-war ?
;-)
Michel
--
| Michel OLAGNON email : Michel....@ifremer.fr|
| IFREMER: Institut Francais de Recherches pour l'Exploitation de la Mer|
| Centre de Brest - B.P. 70 phone : +33-2-9822 4144|
| F-29280 PLOUZANE - FRANCE fax : +33-2-9822 4650|
| http://www.ifremer.fr/ditigo/molagnon/molagnon.html |
I think of it as a spelling corrector that also knows a tiny bit of
grammar. Compilers tend to take spelling and grammar errors as
licenses to do anything they care to. It is a relief to be relieved of
having to even think about whether the variable as typed is one I had
intended to use. All I have to worry about is that it is the actual
one I intended to use and that the intended use is what it should have
been. So the trivial issue is finesed and all that is left are the
real, and harder, ones. Now if the "Do What I Mean" correctors
actually worked ...
IMPLICIT NONE much more than pays for the trivial cost of using it.
The implicit typing convention of Fortran is close to that of mathematics,
using the first letter to know the variable type at a glance is a different
issue from IMPLICIT NONE, and I always found it extremely useful.
IMPLICIT NONE FINDS A NUMBER OF BUGS.
AND IT FINDS THEM *BEFORE* EXECUTION!
E.g., mis-typed names (transposed characters), zero instead of capital OH, etc.
Even assignments like X = O
Even the trickier ones -- untyped procedures that sometimes get overlooked
in a visual inspection, particularly if they are meant to be double precision.
In F77, it can pick up many of the transgressions beyond column 72.
Indirectly, program size has an effect. For larger programs, it's
harder to keep track of these small identifiers. Almost automatically,
I start using longer names which are more mnemonic. With longer
names comes the increased probability that the IMPLICIT NONE
will catch spelling errors. But this change isn't directly *caused*
by the size of the program - only my psychological reaction to that
size. Even in a long program, I tend to use I, J, K, etc. as counters
for the shorter, inner loops. And, again, misspelling them isn't usually
caught by the compiler.
I agree that IMPLICIT NONE is often an irritant. When you want
to quickly throw in a loop to smooth some data (DO L = 1,N) and
L isn't declared. So, you fix that. Then, you later delete the loop
and, the compiler now warns of an unused variable: L. !@*$!
as the cartoon characters say.
--
J. Giles
[description of when and why IMPLICIT NONE is useful, with which I agree]
> I agree that IMPLICIT NONE is often an irritant. When you want
> to quickly throw in a loop to smooth some data (DO L = 1,N) and
> L isn't declared. So, you fix that. Then, you later delete the loop
> and, the compiler now warns of an unused variable: L. !@*$!
> as the cartoon characters say.
Quite. That's why you want to use a language that has general scoping,
including the declaration of variables, preferably in combination with
a folding editor. So may I suggest occam 2.5?
Jan
> I've had grad students tell me that their code "must be correct --
> after all, it complied with no problem." Ouch!
A code that compiles and runs is referred to by a group I used to
work in here as a "Jan Steiner" check case. The name is imortalized
because of the student here who took that as incontrovertable
proof that his code was correct. This was indeed, sufficient to
prove that you could indeed get two real solutions and one
complex one for a 3rd order polynomial with real coefficients.
Who pays attention to that ivory tower theory stuff anyway when
you have proof by example sitting in front of you. :-)
--
Richard Maine
ma...@altair.dfrc.nasa.gov
But FTNCHEK only works on Fortran77 code (unfortunately), whereas IMPLICIT
NONE was only introduced with Fortran90, so they aren't alternatives, you
use whichever is available at the time.
I can only say that now I always use IMPLICIT NONE, and it often finds my
typing mistakes.
--
--
Clive Page,
Dept of Physics & Astronomy,
University of Leicester.
robin wrote:
> "charles d. russell" <crus...@uabmc.edu> writes:
> > After seeing all the stir over GO TO, I'm curious whether there are
> > strong feelings about IMPLICIT NONE (on any side other than its
> > advocates.) For small problems, this seems to me like using
> > double-entry bookkeeping on your pocket change. When I have used it to
> > try to track down a difficult bug, it has never helped. It only finds
> > bugs that are more easily found by a good compiler or by ftncheck.
>
> IMPLICIT NONE FINDS A NUMBER OF BUGS.
> AND IT FINDS THEM *BEFORE* EXECUTION!
>
> E.g., mis-typed names (transposed characters), zero instead of capital OH, etc.
> Even assignments like X = O
> Even the trickier ones -- untyped procedures that sometimes get overlooked
> in a visual inspection, particularly if they are meant to be double precision.
>
> In F77, it can pick up many of the transgressions beyond column 72.
>
Look at this code written in fortran 77 and compiled in Fortran 77:
a = 0H !1. zero instead of capital OH
asdsdl = asdsd1 + 1. !2. misspelling
a1123312 = O !3. O instead of zero 0
Yassasasd = a1123312 + a1123312 + a1123312 + a1123312 + a1123312 + a1123312 ! 4. more than 72
end
1. first line was catched with error message
*** Invalid character(s) at end of statement
2. Next was warning
WARNING - ASDSD1 has not been given an initial value
3. Again warning
WARNING - O has not been given an initial value
4. And finally
WARNING - Characters found after column 72 (use -NO_WARN73 to suppress)
I commented this line to produce exe file.
Then at run time: Program stops at line 2, 3, 4 with message
"Reference to unudentified variable".
Ready!
So what are you talking about?
Use real compilers for PC guys. They were invented 15 years ago.
Even more funny was to read respond of Clive Page below who has to know
what compiler I'm talking about but writes that he is catching errors with 'implicit none'.
-------------
One of ForTRTRTRTRaneers
Your point? All of the warnings and errors were cought by the compiler,
and should be investigated to see why (in a real code, as opposed to
your example) they occurred. Assuming the compiler will catch
*everything* and label it with an explicit message saying "you
misspelled this variable" is silly - nice idea but it'd be a nightmare
to write that compiler...
Jim
Polyhedron Software Ltd.
Programs for Programmers - QA, Compilers, Graphics
************ Visit our Web site on http://www.polyhedron.co.uk/ ************
If you study traffic accidents of the "going the wrong way on a one
way street" sort you find will find that most are the result of folks
taking short cuts, or so I believe I have been told. Not using an
IMPLICIT NONE seems to be behavior that is justified by explanations
that are awfully close to the "I was taking a short cut" when caught
going the wrong way. If you know the neighbourhood well and look
carefully it seems to work a goodly fraction of the time, but ....
(there comes a day when you are in an extra rush so don't look quite
as carefully and .... and #%&^!! )
Perhaps I am just extrapolating my own experience but I expect that
all those who swear by IMPLICIT NONE are folks who can tell more than
a few war stories of various sorts and have learned from being burned
by the trivial type of problems that IMPLICIT NONE prevents. The
closest to a down side is the extra tendency to leave unused declared
variables around after (temporary debugging) code is removed as has
been noted.
FTNCHEK works with some extensions beyond the Fortran 77 standard.
IMPLICIT NONE is one of those.
John Harper, School of Mathematical and Computing Sciences,
Victoria University, Wellington, New Zealand
e-mail john....@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
Gordon Sande wrote:
I've just concretely answered to message without telling road accident stories.
>
> Perhaps I am just extrapolating my own experience but I expect that
> all those who swear by IMPLICIT NONE are folks who can tell more than
> a few war stories of various sorts and have learned from being burned
> by the trivial type of problems that IMPLICIT NONE prevents.
For example? (leaving aside war convictions)
The
> closest to a down side is the extra tendency to leave unused declared
> variables around after (temporary debugging) code is removed as has
> been noted.
Even more funny is that both you USE these compilers.
It is IMPOSSIBLE to run the code with 'warning' like mentioned with /undef.
It is of human nature not to know the most important part of each compiler 'Compiler Opntion'
(two-three pages), usually people prefer diluted digests with blah-blah in this newsgroups.
Mentioned Undef option will tell you what you need. But if someone needs completely clean code
and 'fatal error' message instead of 'warning/comments' there exist appropriate
compiler option for that.
But, sometimes, even a good compiler cannot detect
a use of unset variable: If the mis-spelt (unset)
variable is used as an argument to a procedure whose
interface is implicit:
!--- main.f -----
real :: nnm = 10
call sub(nmm) !! mis-spelling
!....
!-- sub.f ----
subroutine sub(n)
write(*,*) n !! writing an unset var.
!....
(Ftnchek would, I think, catch this error, though.)
I remember helping a student hunt a bug in her code
years ago. She had spent more than half a day before
she came to me for help. Then we spent several hours
before we finally found the error was due to a mis-
spelt variable name. At that time, we didn't know
ftnchek. If I remember correctly, the compiler didn't
catch the error because of a subroutine call, as I
describe above. When I asked her why she didn't use
IMPLICIT NONE, her answer was that her mentor abhors
explicit typing. When I talked with him about implicit
typing, he said it is inefficient when writing code to
interrupt one's own thought by moving the cursor upward
to the declaration section in order to write
declarations. But, I thought (and think) that this
reasoning for implicit typing unsatisfactory, and
suspected, judging from the way he spoke, that his
"real" reason was an emotional one and a matter of
taste.
(What's the moral? Whereas you have a human right
of freedom of religion, you don't have a right to
force others to believe your religion :)
Ryo
Sent via Deja.com http://www.deja.com/
Before you buy.
> Mentioned Undef option will tell you what you need.
Nonsense. You should read Turing's paper on the halting problem, and
contemplate that, in full generality, detecting undefined/uninitialized
variables is equivalent to it. The compiler can help you find simple cases,
up to ingenuity and sweat invested by the compiler writer and the money
of his employer, but no more.
Jan
furu...@ccsr.u-tokyo.ac.jp wrote:
Was sorry to hear the story about poor girl who
spent her evening fighing with stu#$%^& Fortran compiler.
Now listen mine.
Your example:
real :: nnm = 10
call sub(nmm) !! mis-spelling
end
subroutine sub(n)
write(*,*) n !! writing an unset var.
end
Again Compiler had warning:
WARNING - Variable NNM has been given a value but never used
If you missed this message in 120 pages of others,
then at run time you will be stopped immediately
with fatal error
ERROR 112. Reference to undefined variable....
(with your cursor stopped exactly on the variable by the way).
15 seconds.
Stop
End
Whose story is better? Tell this story to your girl
if she still not hates Fortran...
---------
real :: nnm = 10
call sub(nnm) !! No mis-spelling
end
the smart compiler will tell you that
WARNING - In a call to SUB from another procedure, the first argument was of
type REAL(KIND=1), it is now INTEGER(KIND=3)
Again if you've missed it the debugger will stop you at run time
with same fatal message and exactly where roach is.
BTW, I'm sure if you did not used this you have missed other errors too.
Now stay in peace with your religion.
Jan Vorbrueggen wrote:
Use just simple plain regular Fortran.
But distinguish vintage.
> > Quite. That's why you want to use a language that has general scoping,
> > including the declaration of variables, preferably in combination with
> > a folding editor. So may I suggest occam 2.5?
> Use just simple plain regular Fortran. But distinguish vintage.
So the current Fortran standard allows me to write the sematic equivalent of:
INT n.ll.1, n.ll.2 :
REAL32 cost.total.new :
WHILE count < max.trials
SEQ
BOOL in.picture:
SEQ
in.picture := FALSE
WHILE NOT in.picture
SEQ
REAL32 temp :
SEQ
temp, seed := RAN (seed)
n.ll.1 := ll.1 + (INT ROUND ((temp - O.5) * stepscale.1))
temp, seed := RAN (seed)
n.ll.2 := ll.2 + (INT ROUND ((temp - O.5) * stepscale.2))
Methinks not.
Jan
Depends completey on the technology you have available. Them there
fancy PC compilers aren't much good to those of us working on
mainframes. Implicit None is available to us all. The above runs
perfectly happilly compiled on OpenVMS, and writes "0" to the screen. I
expect I could persaude the compiler to produce an error or two, though
the behaviour is perfectly consistent with the standard.
having IMPLICIT NONE at the top of the program is not a replacement for
fancy compiler options (or vice versa), it is an additional safeguard. Its
also an additional safeguard that lives with the file even if I change
compilers.
----
Mike Lay --- micha...@ctsu.ox.ac.uk --- CTSU, Oxford.
"I can barely speak for myself... let alone the CTSU!"
"Help! My computer's falling apart!! The operating system's in 32 bits!"
Good compilers can and do find this sort of error. Static analysers may
catch some, but in general the problem is far too complex for static
analysis.
For example in the case where a single element of a huge array is
undefined, a static analyser would be defeated, but the run-time system
of a compiler can catch it - for example, by initialising all memory to
a special "undefined value" and checking before every use that the value
has been changed from the undefined value. That's how Salford's /undef
switch works, and some other compilers do a similar trick.
The run-time undefined variable checks can catch all *actual* uses of
undefined variables. However they only find errors which are exposed by
the data you use - so the only way to stay safe is to leave them on all
the time.
With comprehensive bounds checking and undefined variable checking, and
a few other things, like protection of constant arguments and dangling
pointers, I don't think there's any way that a Fortran program can
behave unpredictably. It may not do what you want, but it should at
least do it reliably.
There's a little chart on our web site ("Why doesn't it work?") which
attempts to enumerate the causes of "mysterious" failures. I'd be very
interested to know if anyone can add to or qualify any of the items
listed.
--
John Appleyard Jo...@polyhedron.com Jo...@polyhedron.co.uk
Polyhedron Software Ltd.
Programs for Programmers - QA, Compilers, Graphics
************ Visit our Web site on http://www.polyhedron.com/ ************
> When I talked with him about implicit
>typing, he said it is inefficient when writing code to
>interrupt one's own thought by moving the cursor upward
>to the declaration section in order to write
>declarations.
Yes, this brings me back to the days when I wrote in F77
and was forced to use primitive text editors where you
couldn't jump around between the working face of your code
and the declarations section so easily. I wouldn't have
considered using implicit none then, either. Things have
changed at least for me and I find that F90 has more
possibilities for unintended or just very large scope of
variables. When reading a rather complex problem I also
find it convenient to able to right click on a variable
and use the source browser to find the line where it's
declared. Of course for a large program all the variables
should be declared one per line with a brief description
of the variable along with its units if applicable on the
same line. When the type of a variable is implicit there
is not necessarily such an easy path to this description,
and it can be more of a tedious task to discover what a
questionable line of code does and whether the conversion
factors are correct. I would say that this would have
seemed hopelessly pedantic to me at an earlier time but
now code without implicit none always looks suspect to me.
It's true that compilers can check many of the kind of
errors that implicit none does but it's annoying to have
to read the compiler documentation for every project you
are helping different people out with just to get past
this basic stage of verification, and worse on a UNIX
system where there is usually no documentation, just man
pages (this is supposed to be a flame war, isn't it? :) )
Even in small one-off programs I use implicit none and
declare one variable (or a small group of closely related
variables) per line, although usually without descriptions,
and I find that the time required to do so is minimal
compared to the time that would sometimes be required to
find and fix (if their existence is even discovered at all)
the relatively mysterious bugs that can crop up in its
absence. I think that most everyone who has been burned
for a few hours of their time by a single program bug of
this nature uses implicit none quite frequently at this
point.
Catherine.
--
Catherine Rees Lay
> > > A good compiler can make up for not having
> > > IMPLICIT NONE,
> >
> > But, sometimes, even a good compiler cannot detect
> > a use of unset variable: If the mis-spelt (unset)
> > variable is used as an argument to a procedure
> > whose interface is implicit:
> >
> > !--- main.f -----
> > real :: nnm = 10
> > call sub(nmm) !! mis-spelling
> > !....
> >
> > !-- sub.f ----
> > subroutine sub(n)
> > write(*,*) n !! writing an unset var.
> > !....
> >
> > (Ftnchek would, I think, catch this error, though.)
>
> Was sorry to hear the story about poor girl who
> spent her evening fighing with stu#$%^& Fortran
> compiler.
[...]
> Now listen mine.
> Your example:
>
> real :: nnm = 10
> call sub(nmm) !! mis-spelling
> end
>
> subroutine sub(n)
> write(*,*) n !! writing an unset var.
> end
>
> Again Compiler had warning:
> WARNING - Variable NNM has been given a value but
> never used
Well, this is _your_ example, not mine :-) Note that I
wrote an ellipsis at the end of main.f without the
END statement:
!--- main.f --
real :: nnm = 10
call sub(nmm) !! mis-spelling
!...
So, if you use nnm in some way:
!--- main2.f ---
real :: nnm = 10
call sub(nmm) !! mis-spelling
write(*,*) nnm
end
the warning will disappear, I guess.
At least, it is true of one of the theee compilers I
have access to. The other compilers, Sun and DEC,
don't even issue any warning to the main program of
_your_ example. (Maybe, tweaking some compiler switch
would make them issue warnings, but I haven't checked
this possibility. Also, I don't know about the newest
version of these compilers.)
Note that the compiler is not, in any way, able to tell
whether main2.f is wrong or not: nnm is initialized and
used, and the uninitialized variable nmm might be used
as a working area in sub.
(By the way, recall we have been assuming the interface
of sub is implicit.)
I don't remember whether this was really the case for
our poor student; it may have been due to the stu#$%
compiler :-)
> If you missed this message in 120 pages of others,
> then at run time you will be stopped immediately
> with fatal error
> ERROR 112. Reference to undefined variable....
> (with your cursor stopped exactly on the variable by
> the way).
Ah, you seem to be using an extremely good programming
environment. But, that kind of runtime check isn't
always available, and you don't always have a choice.
Jan Vorbrueggen wrote:
To add some fog this was great, me and, beat, even J.G.
didn't understood anything! But it reminded me something
when I've looked into this. What I still remember since
early 198... is that Occam required exact indentation:
you will find yourself 'painting' Occam codes with exactly
two spaces! Is this what you've tried to show us? Great, I said.
It reminded, what amazed me at that time, that the transputer
took 9 processor clock cycles in hardware to evaluate square root.
I have no idea why just square root was so special for them.
You probably may add here more fun..
OK, but some of us are practical folks and let's return to our sheeps.
You showed people, now show the money. Are you still running
transputer in your basement?
How specifically would occam diagnose mentioned here common
mistakes which I showed even free Salford compilers crunched
so effectively rendering annoying like hell implicit none
rudimental for this purpose? Can you compile/run above examples ?
-----
John Appleyard wrote:
> In article <89nrtt$89$1...@nnrp1.deja.com>, furu...@ccsr.u-tokyo.ac.jp
> writes
> >But, sometimes, even a good compiler cannot detect
> >a use of unset variable: If the mis-spelt (unset)
> >variable is used as an argument to a procedure whose
> >interface is implicit:
> >
> > !--- main.f -----
> > real :: nnm = 10
> > call sub(nmm) !! mis-spelling
> > !....
> >
> > !-- sub.f ----
> > subroutine sub(n)
> > write(*,*) n !! writing an unset var.
> > !....
> >
> >(Ftnchek would, I think, catch this error, though.)
>
> Good compilers can and do find this sort of error. Static analysers may
> catch some, but in general the problem is far too complex for static
> analysis.
>
> For example in the case where a single element of a huge array is
> undefined, a static analyser would be defeated, but the run-time system
> of a compiler can catch it - for example, by initialising all memory to
> a special "undefined value" and checking before every use that the value
> has been changed from the undefined value. That's how Salford's /undef
> switch works, and some other compilers do a similar trick.
>
> The run-time undefined variable checks can catch all *actual* uses of
> undefined variables. However they only find errors which are exposed by
> the data you use - so the only way to stay safe is to leave them on all
> the time.
>
> With comprehensive bounds checking and undefined variable checking, and
> a few other things, like protection of constant arguments and dangling
> pointers, I don't think there's any way that a Fortran program can
> behave unpredictably. It may not do what you want, but it should at
> least do it reliably.
>
> There's a little chart on our web site ("Why doesn't it work?") which
> attempts to enumerate the causes of "mysterious" failures. I'd be very
> interested to know if anyone can add to or qualify any of the items
> listed.
>
Addition exactly to the point of this thread
which we considered in really compiled example above.
"IMPLICIT typing errors" :
In the absence of "IMPLICIT NONE" a misspelled variable name will
wrongly cause a new variable to be created.
INTEGER I0
IO = 2
To your recommendation "Use IMPLICIT NONE in new code"
should be added "Or just use /undef compiler option where possible
as more natural, simple and powerful alrernative".
---------------
consider the following toy code fragment:
REAL(4)::abc, answer
INTEGER(4)::i
abc = 0.
DO i=1,10
abd = abc + 1. ! "abd" is a misspelling of "abc"
END DO
answer = abc
In this case, it is very difficult for the machine to detect that a
misspelling of "abc" has occurred on line 3. There are no uninitialized
variables, yet the answer is wrong. abd is the same REAL(4) type as abc, so
there is nothing wrong with the operation occurring in line 3.
A canny optimizer would optimize out the DO loop, realizing that it did not
affect the answer. If you were lucky, the compiler would tell you that it
had optimized out the DO loop, and this would give you a hint that something
was wrong. Or, it might tell you that the computation of abd did not affect
the value of answer.
But IMPLICIT NONE would instantly catch the error.
IMPLICIT NONE would catch this error.
Robert Orban wrote:
> In article <38C0FE1A...@netnetnet.net>, n...@netnetnet.net says...
> >
> >
> >
> >John Appleyard wrote:
> >
> >> In article <89nrtt$89$1...@nnrp1.deja.com>, furu...@ccsr.u-tokyo.ac.jp
> >> writes
> >> >But, sometimes, even a good compiler cannot detect
> >> >a use of unset variable: If the mis-spelt (unset)
> >> >variable is used as an argument to a procedure whose
> >> >interface is implicit:
> >> >
> >> > !--- main.f -----
> >> > real :: nnm = 10
> >> > call sub(nmm) !! mis-spelling
> >> > !....
> >> >
> >> > !-- sub.f ----
> >> > subroutine sub(n)
> >> > write(*,*) n !! writing an unset var.
> >> > !....
> >> >
> >> >(Ftnchek would, I think, catch this error, though.)
> >>
Piece of cake.
Here is trace of this error WITHOUT implicit none
*** Variable ABD has been given a value but never used
1 ERROR [<main program> FTN95/Win32 v2.00d]
*** Compilation failed
James Giles wrote:
> The common exceptions are the use of the misspelled identifier in the
> argument list of a procedure call (which might both set and use the
> variable on successive calls), or as a global variable. In these cases,
> a single misspelling might go unnoticed.
Can you write down here your example ?
James Giles wrote:
> netnet wrote in message <38C1C060...@netnetnet.net>...
> Program test
>
> ABC = 0.0
> DO I = 1, 20
> CALL SUB1(ADC) !misspelled ABC
> END DO
> PRINT *, ABC
>
> End Program test
>
> Without implicit none, the compiler should not complain about
> ADC being uninitialized because the subroutine might do so. It
> should also not complain about ADC not being used, because
> the subroutine might do so. In fact, the purpose of the argument
> might be to make SUB1 a PURE procedure (in the F95 sense),
> and still allow it to preserve information from one call to another
> (which this example would legally do). So , the compiler shouldn't
> complain since it's a legal use.
>
Right, it shouldn't and my compiler does not complain here.
Misspelling though is found, we considered already this
example. How? Because misspelled varaible is not
defined inside SUB1 and is easily catched.
>
> Program test
>
> COMMON /TESTCOM/ ADC, ... other stuff ... !misspelled ABC
>
> ... code involving ABC (correcly spelled) and the other
> variables in common, and some procedure calls ...
>
> End Program test
>
> Again, without implicit none, the misspelling should not cause a message
> about ADC being unitialized - some other procedure may be setting it.
> And, it shouldn't complain about it being unused - it's appropriate as
> a placeholder.
Same things, we saw this already, this should not catched at compile time but
is found at run time in a snap.
Note that the same is possible if the variable is in a
> MODULE instead. It is not illegal to USE a MODULE that declares
> variables that you don't use (though I suppose you could instrument a
> compiler to warn about such cases - how desirable would that be?).
>
> These are two possible exceptions to the general rule that the compiler usually
> *can* identify misspellings even if IMPLICIT NONE is absent. They're
> not, in any absolute sense, all that common. Perhaps more common
> is to misspell one variable as another one, but even IMPLICIT NONE
> doesn't catch that one.
...while catch for undefined variable at run time still will do that.
Besides as Appleyard noticed this method in this compiler
(which costs its gold) has additinal bonuses implicit none will never
find and which is coronal use of fortran: arrays (I even do not say
about virtual common).
In the old days, the compiler would have complained that ABD was
assigned but never used. Are compilers common that don't? (I don't
honestly know since I usually use IMPLICIT NONE and the only
compilers I have here at home require it. And no, I'm not going to
remote login to somewhere just to test this characteristic of more
compilers.)
In general, you have to use the same misspelling twice for the compiler
not to at least warn you about it. But then, you generally have to use
an identifier twice (at least) or the compiler will warn about it, even if
the identifier is spelled correctly and explicitly declared.
The common exceptions are the use of the misspelled identifier in the
argument list of a procedure call (which might both set and use the
variable on successive calls), or as a global variable. In these cases,
a single misspelling might go unnoticed.
--
J. Giles
Program test
ABC = 0.0
DO I = 1, 20
CALL SUB1(ADC) !misspelled ABC
END DO
PRINT *, ABC
End Program test
Without implicit none, the compiler should not complain about
ADC being uninitialized because the subroutine might do so. It
should also not complain about ADC not being used, because
the subroutine might do so. In fact, the purpose of the argument
might be to make SUB1 a PURE procedure (in the F95 sense),
and still allow it to preserve information from one call to another
(which this example would legally do). So , the compiler shouldn't
complain since it's a legal use.
Program test
COMMON /TESTCOM/ ADC, ... other stuff ... !misspelled ABC
... code involving ABC (correcly spelled) and the other
variables in common, and some procedure calls ...
End Program test
Again, without implicit none, the misspelling should not cause a message
about ADC being unitialized - some other procedure may be setting it.
And, it shouldn't complain about it being unused - it's appropriate as
a placeholder. Note that the same is possible if the variable is in a
MODULE instead. It is not illegal to USE a MODULE that declares
variables that you don't use (though I suppose you could instrument a
compiler to warn about such cases - how desirable would that be?).
These are two possible exceptions to the general rule that the compiler usually
*can* identify misspellings even if IMPLICIT NONE is absent. They're
not, in any absolute sense, all that common. Perhaps more common
is to misspell one variable as another one, but even IMPLICIT NONE
doesn't catch that one.
--
J. Giles
Shouldn't be. The name of the argument inside the subroutine
is not spelled the same anyway. And, if the subroutine is
independently compiled, there actually should be no way for the
compiler to tell.
SUBROUTINE SUB1(X)
REAL X
... etc. ...
END SUBROUTINE SUB1
If you're relying on a compiler initializing all variables to some
NAN, the subroutine can bypass that (especially if it doesn't
expect the argument to be initialized on every call anyway).
In any case, the implementation has no way of knowing that
the reason the variable is undefined is that it was misspelled in
the caller. From the subroutine's point of view, a uninitialized
argument may be a perfectly valid possibility.
Using F200x proposed intrinsics:
SUBROUTINE SUB1(X)
REAL::X
... other declarations ...
IF (IEEE_IS_NAN(X)) THEN ! Assume X needs to be initialized
X = 50.0
END IF
... code using X ...
END SUBROUTINE SUB1
The same thing goes for misspelling in a global declaration. It
is not illegal for such a variable to be uninitialized, or "undefined"
(however you claim to be detecting this).
--
J. Giles
James Giles wrote:
> netnet wrote in message <38C1E64E...@netnetnet.net>...
> ....
> >> Program test
> >>
> >> ABC = 0.0
> >> DO I = 1, 20
> >> CALL SUB1(ADC) !misspelled ABC
> >> END DO
> >> PRINT *, ABC
> >>
> >> End Program test
> ....
> >Right, it shouldn't and my compiler does not complain here.
> >Misspelling though is found, we considered already this
> >example. How? Because misspelled varaible is not
> >defined inside SUB1 and is easily catched.
>
> Shouldn't be. The name of the argument inside the subroutine
> is not spelled the same anyway. And, if the subroutine is
> independently compiled, there actually should be no way for the
> compiler to tell.
>
> SUBROUTINE SUB1(X)
> REAL X
> ... etc. ...
> END SUBROUTINE SUB1
>
Of course spelling in main program and subroutine is not obliged
to be same, why do you think even for a moment that this compiler
authors were so stupid? And of course compiled independently
or in the same file does not matter at all, because all debugging
information will be supplied.
And of course I'm not guessing but have it in front of me: compiler
finds undefined or 'unitialized' variables in this case too: it works like
Orkin pest control.
>
> If you're relying on a compiler initializing all variables to some
> NAN, the subroutine can bypass that (especially if it doesn't
> expect the argument to be initialized on every call anyway).
> In any case, the implementation has no way of knowing that
> the reason the variable is undefined is that it was misspelled in
> the caller. From the subroutine's point of view, a uninitialized
> argument may be a perfectly valid possibility.
>
Since all this looks kind of unusual even for serious fortraneers (?!)
I'll repeat that misspeling of YOUR examples is catched not at
compile time (in different previous cases above were catched
also compile time errors ) but at run time with debugger 'tuned' specially
for this purpose (just one more option).
>
> Using F200x proposed intrinsics:
>
> SUBROUTINE SUB1(X)
> REAL::X
> ... other declarations ...
> IF (IEEE_IS_NAN(X)) THEN ! Assume X needs to be initialized
> X = 50.0
> END IF
> ... code using X ...
> END SUBROUTINE SUB1
>
> The same thing goes for misspelling in a global declaration. It
> is not illegal for such a variable to be uninitialized, or "undefined"
> (however you claim to be detecting this).
>
Same dilusion that compiler always doing that at compile time.
Please detune from this stereo: something yes and something not,
and all works in full accordance with the standard.
I couldn't check your NaN example from F2_NaN standard,
sorry, still can't fly into future :-).
netnet wrote:
> ...
> finds undefined or 'unitialized' variables in this case too: it works like
> ...
I'm not inventing new terminology here, it's just 'misspelling', read: uninitialized
I do (really) take your point that compilers exist that make IMPLICIT NONE
almost redundant, and one is even free for personal use (but only F77). I'm
also getting resigned to the fact that no matter how often the mechanism and
benefits of run-time checks are explained, even the best informed people
remain ignorant or unconvinced until they actually use them...
However, here's one moderately common case, which doesn't involve
mis-spelling, where IMPLICIT NONE catches a bug which, sometimes at
least, won't get caught by run-time checks.
subroutine Reset_Frog_Count
include 'Frogs.inc'
Number_of_Frogs= 0
more code that does things with Number_of_Frogs
end
Here, Number_of_Frogs is a COMMON variable, defined in Frogs.inc
(a module would do as well), and initialised and used in other subprograms.
If we now (accidentally) remove the include statement (or if we forgot to
put it in in the first place), the code remains valid, and may well pass all
the run-time checks, but will not behave as intended.
IMPLICIT NONE would catch the problem, by observing that
Number_of_Frogs is not declared (on a bad day, I'd probably compound
the error by just inserting the required declaration and continuing :<).
Most
static analysers won't catch it (after all the code is valid). However,
ours
would observe that the name Number_of_Frogs is used both for a local
variable and for a COMMON variable (not an error, but suspicious).
The two are not synonyms. An unitialized variable is not necessarily
one that has been misspelled. Nor is it necessarily illegal. Turning
on a debugger option to detect unitialized variables will only tell
you whether they've been initialized. That's not even illegal if
control hasn't reached the part of the program that initializes the
variable yet. (By the way, does it work for INTEGER, CHARACTER,
and LOGICAL? How? There are no NANs for those data types.
For most implementations, *any* bit pattern is a legal value for those
types.)
You seem to be under the impression that identifying an unitialized
variable automatically implies that an errror has occurred. That's
not necessarily the case. The language does not require variables
to be initialized. They must become defined before you first try
to evaluated them - but that can happen very late in a program's
execution, and the variable can be passed around between procedures
many times before that happens.
--
J. Giles
>
>netnet wrote in message <38C22FA6...@netnetnet.net>...
>>
>>
>>netnet wrote:
>>
>>> ...
>>> finds undefined or 'unitialized' variables in this case too: it works like
>>> ...
>>
>>I'm not inventing new terminology here, it's just 'misspelling', read: uninitialized
>
>The two are not synonyms. An unitialized variable is not necessarily
>one that has been misspelled. Nor is it necessarily illegal. Turning
>on a debugger option to detect unitialized variables will only tell
>you whether they've been initialized. That's not even illegal if
>control hasn't reached the part of the program that initializes the
>variable yet. (By the way, does it work for INTEGER, CHARACTER,
>and LOGICAL? How? There are no NANs for those data types.
The first system to systematically chase undefined variables that I am
aware of was WatFor for IBM 7040's. It used a cheat as it deliberately
stored bad parity into memory and then declared that all bad parity
references were for use of undefined variables. So on the exceedingly
rare case of a real bad parity you could be a bit confused. Other than
that you will read the fine print and find that there is a forbidden
value which is declared to be off limits. The bad parity check was a
thirty line assembly hack. The forbidden value scheme is a lot of work
as even the WatFor folks found out when they tried to replicate their
very good feature on IBM 360/xx's back when xx was still small like
50. So if you are using character data for other than printable and
other defined characters you have a risk of finding out about the fine
print that you may never have examined carefully. For systems without
NaNs for floating there are usually an adequate supply of otherwise
illegal configurations, logical is only supposed to have two states
(before vendor extensions) under control of the system and integers
cause the forbidden value to be a bother. This is particularly true if
the user and the system implementors have similar notions of
distinctive flag values.
None of which lessens the need for or utility of IMPLICIT NONE. I am
of the belt and suspenders school and like both. All of the arguements
so far against either IMPLICIT NONE or undefined variable checking
under a debugger seem to be of the "I never make mistakes so why do I
need the extra bother?" variety. There is some merit in the arguement
that having to declare variables is an interruption which seems to
rank with the bother of having to remove the declaration after its
temporary debugging use. I expect that the old idiom of "penny wise
and pound foolish" fits both better than their proponents would care
to admit. You are quite correct that undefined variable checking is
not a replacement for IMPLICIT NONE.
>For most implementations, *any* bit pattern is a legal value for those
>types.)
>
>You seem to be under the impression that identifying an unitialized
>variable automatically implies that an errror has occurred. That's
>not necessarily the case. The language does not require variables
>to be initialized. They must become defined before you first try
>to evaluated them - but that can happen very late in a program's
>execution, and the variable can be passed around between procedures
>many times before that happens.
Unfortunately some of the systems that implement undefined variable
checking seem to treat the setting of an undefined variable in some
circumstances in a subroutine as an error according to their current
implementations. (They act as if one must reference it before setting
it in those curious circunstances!) They agree that such treatment is
in fact a bug but the fix seems a bit slow in coming. I do not know
the sorry internal details of the bug but it appears that this is in
fact a side effect of some other problem. Either way as a user I am
less than pleased, as the unnamed vendor knows rather well from the
apologies from their senior folks. One of the downsides of undefined
variable chacking is that it makes the system larger with all the
attendent bothers. The checklist purchasing which seems to greatly
value optimizations and to give zero credit for good debugging
facilities is not going to get a lot of good debugging support
developed. Bob Runyan's notion that diferent systems should be given
credit for differing strengths so much that one routinely uses several
systems has a lot going for it.
Poor implementation of a good idea is not directly an arguement
against the idea, and in this case it is a poor implementation of some
technically involved related issues which also seem to botch up the
subscript checking and even pointer passing with no debugging present.
>
>--
>J. Giles
>
>
I think it's conceivable that you may have misunderstood how netnet's
compiler does its work. It doesn't use NaNs, and works equally with
data of all types. And it does its check at the last possible moment -
just before the uninitialised variable is actually used - so the errors it
reports are genuine violations of the standard. You can pass data
around through as many argument lists as you like, and a problem in
a single array element is as easy to find as one in a scalar. In principle
it finds every *actual* use of an uninitialized variable, and it's trivial
to use - no fancy debuggers to learn - just an extra switch on the
compiler command line.
It does the trick by painting all memory - just after allocation - with a
special "undefined" bit pattern. Then whenever a piece of memory is
used, it checks that the value has been changed from the "undefined"
value. If it has not, an error is reported. It's really very simple.
Now I know what you're going to say! It is possible to get false
positives using this method. The "undefined" bit pattern may arise in
normal use. This is true, and limits its application to some extent.
However, in practice, false positives are vanishingly rare in 32 bit
variables. I've been using this method more or less daily for a
decade or more (in fact my first exposure to it was in the 70s), and
I think I remember one false positive (but hundreds of genuine ones).
If the risk of false positives really bothers you, a different
implementation is possible; allocate a shadow for every piece of
data, and use bits in the shadow to indicate when bits of the actual
data are set. That gives you single bit resolution, and no false
positives, but at the cost of a doubled memory footprint.
If you can't use netnet's compiler, Polyhedron offers a tool which
does the same trick by instrumenting your Fortran. That way, you
can use any compiler you like, and get the equivalent of /undef.
The tools works with F77 + extensions.
I've lost count of the number of times I've explained this in c.l.f -
including a previous post in this thread :< I apologise for wasting
bandwidth by doing it again, but IMHO, it really is a great shame
that this technique is not more widely understood and used;
software really could be made more reliable, and huge amounts of
debugging time could be saved by a simple compiler switch.
> None of which lessens the need for or utility of IMPLICIT NONE. I am
> of the belt and suspenders school and like both. All of the arguements
> so far against either IMPLICIT NONE or undefined variable checking
> under a debugger seem to be of the "I never make mistakes so why do I
> need the extra bother?" variety. There is some merit in the arguement
> that having to declare variables is an interruption which seems to
> rank with the bother of having to remove the declaration after its
> temporary debugging use. I expect that the old idiom of "penny wise
> and pound foolish" fits both better than their proponents would care
> to admit. You are quite correct that undefined variable checking is
> not a replacement for IMPLICIT NONE.
I guess I've spent about 14 years without using implicit none and another 8 years using
implicit none. My experience is that the percentage of errors caused by implicit typing
is vastly different in different programming domains. It may be that it is of a higher
percentage of the total errors in a "numerical calculation" environment, but in my case,
it has been a vanishingly small percentage of the errors in my "system programming"
environment. Since we build our own special purpose peripheral devices that typically
interface via shared memory (sometimes single, sometimes multiple CPUs), about 98+ percent
of all programming errors have been in incorrect initialization, instruction, status
interpretation, interrupt handling, data buffering to a storage medium, and otherwise
interfacing to these peripheral devices. Even though the interfaces are extremely simple
to use, there are some that just cannot grasp the concept of 1) set instruction word, 2)
generate interrupt, 3) check status word, 4) handle errors, 5) continue with next
operation. There seems to be an expectation on the part of some "software types" that
hardware will respond immediately (and without ever failing) to interrupts and so status
words never need to be checked. Then there were those times when some obscure piece of
code set an incorrect instruction value which caused a device to enter self-test mode,
wiping out a whole shift of setup work...
I still stand by my preference of omitting implicit none for small tools, but I always use
it in larger applications where every little bit of additional error checking helps.
--
Gary Scott
mailto:sco...@flash.net
In which case, it would fail to complain about the example I gave
(in which the misspelled variable was never used before it was
defined, but it was not the one intended to be passed). The example
fails to be detected by a test for uninitialized data no matter *how*
that test is accomplished.
To rewrite the example so that it doesn't rely on F200x features:
Program test
logical flag = .false.
Integer ABC = 0
Do I = 1, 50
Call SUB1(ADC, flag) ! ADC is ABC misspelled
... code using ABC, possibly redefining ABC ...
End Do
End Program test
Subroutine SUB1(X, before)
logical before
integer X
if (.not.before) then
X = ... some expression initializing X ...
before = .true.
end if
... code using, possibly resetting X ...
End Subroutine SUB1
Every path through the code initializes ABC before it is
ever used. Every path through the code initializes X before
it is used. Every path through the code initializes, and uses,
ADC - and the initialization occurs before any use.
This case is rare (as I clearly stated before). It does demonstrate
that there exist instances of a single misspelling that aren't possible
to catch without IMPLICIT NONE. More common are those cases
where you misspell a variable, but the misspelling matches another
legitimate variable - but even IMPLICIT NONE doesn't catch that.
Usually cases of a single misspelling of a variable name are caught
without heroic implementation strategies or checks on undefined
variables. These, as I stated before, are caught by compilers which
tell you of variables set but not used, or variables used but never set.
The fact that only the rarer instances are missed calls into question the
real value of additional features to catch the problem. Especially
since IMPLICIT NONE is also an available tool (this whole thread
is being conducted in the strange assumption that you're not using
IMPLICIT NONE)
--
J. Giles
I like to use a split window editor. Vim or emacs, say, others too. I keep
one small window near the declaration section, and one near the code I'm
working on. As I need to add new variables, I just type them in, without
losing my view of the fresh code.
Pencil and paper work pretty well too...on systems where a split screen editor
is unavailable.
Andrej
--
!------------------------------------------------------------------------------!
! Dr Andrej Panjkov, Analyst/Programmer !
! Numerical Modelling Project, Coal Mine Engineering Group !
! CSIRO Division of Exploration and Mining !
! Queensland Centre for Advanced Technologies Tel: +61 7 3212 4693 !
! PO Box 883, Kenmore (Brisbane), Fax: +61 7 3212 4455 !
! Queensland, Australia, 4069 Mobile: 0417 551 435 !
!------------------------------------------------------------------------------!
! Andrej....@dem.csiro.au A.Pa...@uq.net.au !
!------------------------------------------------------------------------------!
[...]
> > But IMPLICIT NONE would instantly catch the error.
>
> Piece of cake.
>
> Here is trace of this error WITHOUT implicit none
>
> *** Variable ABD has been given a value but never used
> 1 ERROR [<main program> FTN95/Win32 v2.00d]
> *** Compilation failed
I dunno. To me, it seems to be fallacious to point to the output of one
compiler as an argument against the merits of using IMPLICIT NONE. What if
I'm using another compiler?
Not all compilers will default to flagging this as an error severe enough to
stop compilation. Some compilers may not even give warnings about this. Most
lint-style code analyzers will warn about this.
My policy is: use IMPLICIT NONE, *and* use all the compiler checks that you can
during development and testing. Use a split screen editor (one screen buffer
may be the piece of paper next top your keyboard :-) ), so you can add in type
declarations quickly.
On this thread:
While I can see great value in the use of run-time checks for accesses to
unitialised variables, surely it makes sense to catch as many bugs as possible
at compile time as well?
I have lost enough time trying to track down type mismatches at procedure calls
in implicitly typed code. IMPLICIT NONE is too valuable to pass up, even
as a non-standard extension to Fortran 77.
James Giles wrote:
> netnet wrote in message <38C22FA6...@netnetnet.net>...
> >
> >
I will just give binary respond to your post to eliminate further sprawl
and ultimate isolation of the misunderstanding.
The two are not synonyms. 1
An unitialized variable is not necessarily one that has been misspelled. 1
Nor is it necessarily illegal. 1
Turning on a debugger option to detect unitialized variables will only tell you whether they've been initialized. 1
That's not even illegal if control hasn't reached the part of the program that initializes the variable yet. 1
(By the way, does it work for INTEGER, CHARACTER, and LOGICAL? 0 on Character, 1 for others
How? There are no NANs for those data types. For most implementations,
*any* bit pattern is a legal value for those types.) NaN
You seem to be under the impression that identifying an unitialized
variable automatically implies that an errror has occurred. 0
That's not necessarily the case. 1
The language does not require variables to be initialized. 1
They must become defined before you first try to evaluated them ... 1
..but that can happen very late in a program's execution, and the variable can be
passed around between procedures many times before that happens. 1
You see since I (better say compiler authors) did not supposed anything wrong.
all is clear.
Of course! Perhaps you miss the point of this thread.
There are persons who claim that IMPLICIT NONE is
redundant because compilers can catch almost all the
errors that IMPLICIT NONE will catch. I pointed out
that in the absence of IMPLICIT NONE, compilers usually
miss a certain type of errors that IMPLICIT NONE will
catch (, although I learned that there are good
compilers that emit code such as cathes that type of
errors at runtime).
James Giles wrote:
>
> To rewrite the example so that it doesn't rely on F200x features:
>
> Program test
Please do the same binary respond with your example, no sketchy
ideas, no additional freedom about possible and not possible nuances,
just valid text (and at least compile it in your compiler) to removes guessing,
and possible distortion, understanding or misunderstanding, whatever.
Gary Scott wrote:
>
> I still stand by my preference of omitting implicit none for small tools, but I always use
> it in larger applications where every little bit of additional error checking helps.
> --
I think you and others with their own compilers are left with no choice.
John Appleyard wrote:
> I do (really) take your point that compilers exist that make IMPLICIT NONE
> almost redundant, and one is even free for personal use (but only F77).I'm
> also getting resigned to the fact that no matter how often the mechanism and
> benefits of run-time checks are explained, even the best informed people
> remain ignorant or unconvinced until they actually use them...
By some deeply psychological reason everybody prefer to stay with his own
fortran 'religion' even if this religion is MS fortran 5.1.
>
> However, here's one moderately common case, which doesn't involve
> mis-spelling, where IMPLICIT NONE catches a bug which, sometimes at
> least, won't get caught by run-time checks.
>
> subroutine Reset_Frog_Count
> include 'Frogs.inc'
> Number_of_Frogs= 0
> more code that does things with Number_of_Frogs
> end
>
> Here, Number_of_Frogs is a COMMON variable, defined in Frogs.inc
> (a module would do as well), and initialised and used in other subprograms.
>
> If we now (accidentally) remove the include statement (or if we forgot to
> put it in in the first place), the code remains valid, and may well pass all
> the run-time checks, but will not behave as intended.
>
> IMPLICIT NONE would catch the problem, by observing that
> Number_of_Frogs is not declared (on a bad day, I'd probably compound
> the error by just inserting the required declaration and continuing :<).
> Most
> static analysers won't catch it (after all the code is valid). However,
> ours
> would observe that the name Number_of_Frogs is used both for a local
> variable and for a COMMON variable (not an error, but suspicious).
Seems John probably tried to explain this...
From your words one can feel the roasted smell (no, not frogs) but just
to have real taste and remove possible confusion can you provide
small and complete fortran text for this example?
I don't see how it helps since the previous was perfectly clear, but:
Program test
logical :: flag = .false.
REAL :: ABC = 0.0
Do I = 1, 50
Call SUB1(ADC, flag) ! ADC is ABC misspelled
ABC = ABC - SQRT(ABC)
Print *, ABC
End Do
End Program test
Subroutine SUB1(X, before)
logical :: before
REAL :: X
if (.not.before) then
X = 3
before = .true.
end if
X = 2*X + 57
Print *, X
End Subroutine SUB1
Every path through the code defines X before it is used. Every path
through the code defines ABC before it is used. ADC is the misspelling
of ABC, but it's use is perfectly legal here (it gets both defined and used
within the subroutine). In fact, nothing (that I know of) in this program
is illegal under the rules of F90. In particular, there are no instances
of any attempted use of undefined variables.
This is not a common problem, but I have seen programs in which a
procedure is called many times in a set sequence. The first call of the
sequence is recognized by some settings of a few arguments of the
procedure, and the rest of the arguments are initialized by the procedure
call. On subsequent calls to the procedure, all the arguments are used
normally. So, this kind of thing does happen. In any event, it demonstrates
that the set of misspellings that aren't caught by testing for uninitialized
variables is not empty.
Another possibility to detect the error is to use an explicit interface.
If the INTENT of X is declared as INOUT, and you have an explicit
interface, ADC would have to be initialized before SUB1 gets called.
That's part of the requirements of the INTENT mechanism. (This
means that you can't use a procedure of the old fashioned kind that
sometimes initializes a variable and other times just uses it if you specify
an explicit INTENT. :-( ) But, since IMPLICIT NONE catches the
error just fine, what more is needed?
--
J. Giles
OK - here it is. It's not a common error, but it's the sort of thing
that really does happen, especially in larger programs. As I've said
elsewhere, I think run-time checks are wonderful, but they don't IMHO
quite remove the need for IMPLICIT NONE.
! As it stands, this program does not work as intended because the
! INCLUDE file has been omitted or deleted from the subroutine.
! /undef finds nothing to complain of
!
! If you uncomment "implicit none", an error is reported. If you put
! the include file in the subroutine, the program works as intended
!
program frogs
! implicit none
! include 'Frogs.inc' expanded in line for clarity (next 2 lines)
integer Number_of_Frogs
common Number_of_Frogs
print *,'Enter Number of Frogs'
read * , Number_of_Frogs
call Reset_Frog_Count
print *,'Number of Frogs is now ',Number_of_Frogs
end
subroutine Reset_Frog_Count
! implicit none
print *,'Enter Number of Frogs'
read * , Number_of_Frogs
print * , 'Frog count reset to ' , Number_of_Frogs
end
--
John Appleyard Jo...@polyhedron.com Jo...@polyhedron.co.uk
Polyhedron Software Ltd.
Programs for Programmers - QA, Compilers, Graphics
************ Visit our Web site on http://www.polyhedron.co.uk/ ************
Catherine.
--
Catherine Rees Lay
Well, perhaps it is due to painful experience. :-)
Take my own experience of working with Fortran for a total of 17 years
starting when I was a student in 1969 with F66 on a CDC6600. [I was not
using Fortran at all during the other 13 years since 1969.] I made a quick
estimate and think I can claim at least moderate use or familarity with 9
different Fortran compilers, plus having heard about the features of several
more. That does not make me a Fortran environment expert by any means, but
shows a sample of the range of experience for someone who has been using
Fortran for a while. None of the nine that I had available for my primary
hardware (ranging from supercomputer to superminicomputer to
minisupercomputer) could support anything close to the degree of error
checking that 'netnet' supposes should be always available in a compiler.
And none of these nine compilers are/were MS Fortran 5.1.
Given that past experience, when I'm thinking as a Fortran program
developer, even if my current development compiler supported that degree of
error checking, I would not be confident that my next compiler would provide
similar support. Given the continual turmoil and vast rate of change in the
computer hardware field, it would seem shortsighted in the extreme to
believe all future work could be done in the same compiler with the same
target architecture. Past experience suggests that I'll have to be able to
deal with a new compiler every two to five years. I would take advantage of
those enhanced debugging features when they were available, but only when a
majority of the leading compilers support such features would I adjust my
style to rely on them.
I recommend using IMPLICIT NONE, and many other good coding practices
especially for larger applications, but often don't bother for small
programs. And when I'm modifying existing applications, I stay with the
existing implementation style unless I'm prepared to rework the whole
application. Maintaining applications that use multiple styles is much more
difficult than ones that stick to a single style.
- Patrick McGehearty
>Another possibility to detect the error is to use an explicit interface.
>If the INTENT of X is declared as INOUT, and you have an explicit
>interface, ADC would have to be initialized before SUB1 gets called.
>That's part of the requirements of the INTENT mechanism. (This
>means that you can't use a procedure of the old fashioned kind that
>sometimes initializes a variable and other times just uses it if you
specify
>an explicit INTENT. :-( )
If only that were true, James! INTENT(INOUT) doesn't mean that you
promise to actually use the value of X when it's passed in on every
call nor that you are going to set the value of X on every call but
that you reserve the option to do either on some calls to the subroutine.
Not all (or even most or perhaps any) compilers will catch this bug
through use of INTENT. INTENT works consistently for variables that
are declared INTENT(IN) and blatantly set in the subroutine and
has a chance to work for variables declared INTENT(OUT) and used
but never set in the subroutine but that's about all that it can do
at least on many compilers.
Catherine Rees Lay wrote:
I think Catherine's answer is what could happen with this poor girl in
this thread above if she would use good Fortran compiler.
She would LOVE it.
All right, despite of rear and specific circumstance it might happen you
convenced me to look into joint use of both features. It will not happen
any time soon because codes are enormous by sizes (in kilobytes soon
twice of Tolstoy War and Peace book, but mostly war. Headers and
declarations may increase it exponentially adding difficulties...but we'll see).
If you will find other cases please report it.
However, it also doesn't mean the same thing as leaving the INTENT
unspecified. At least one compiler I have issues a fatal message if it
can determine that an actual argument associated with an INTENT(INOUT)
dummy variable has not been initialized. Evidently Lahey (at least)
considers it an obligation required by the standard to initialize such
variables.
>Not all (or even most or perhaps any) compilers will catch this bug
>through use of INTENT. INTENT works consistently for variables that
>are declared INTENT(IN) and blatantly set in the subroutine and
>has a chance to work for variables declared INTENT(OUT) and used
>but never set in the subroutine but that's about all that it can do
>at least on many compilers.
Ah, what you can count on from a compiler and what is required by the
standard are often two different things. Compilers are not required to
find violations of the standard (except for a few that are explicitly described).
In this case, I believe it may really be a violation of the standard to pass
an undefined actual argument to an INTENT(INOUT) dummy in a
procedure call.
Anyone that has the specific differences between INOUT and unspecified
INTENT memorized is welcome to disprove my present position - because
I would prefer to be wrong. :-)
It is because INOUT is not the same as leaving INTENT unspecified
that subset compilers which require explicit INTENT can't always be
used for all programming problems. I know that one of the differences
between INOUT and unspecified INTENT is that you can't use a literal
as an actual argument to an INOUT dummy (even though the procedure
never attempts to define the argument on that particular call). Many old
programs used to rely on being able to do such things.
Suppose you have a general I/O procedure for some modeled device.
A call to it with CALL GEN_IO(1.23, OUT) where OUT is a named
constant specifying an operation code for the device (output in this case)
means to send the value of the first argument to the device. And a call
to the same procedure CALL GEN_IO(VAR, IN), where IN is the
code for input, fetches a value from the devices and stores it in the
first argument. This is perfectly sound, but no explicit INTENT would
allow the behavior. (Note, the GEN_IO doesn't have to be a
physical device - rename it as STACK, and rename OUT as PUSH,
and rename IN as POP. An unusual, but still reasonable implementation.)
--
J. Giles
> In this case, I believe it may really be a violation of the standard to pass
> an undefined actual argument to an INTENT(INOUT) dummy in a
> procedure call.
I don't believe it - either that the standard says this or that it was
intended to. I'm afraid that I can't point to the section that doesn't
have such a requirement in it. (Well, I can point to lots of such sections,
but that doesn't prove much). Its generally difficult to prove by specific
citation that something is not in the standard. Sometimes there is an
example that makes it explicit, but I don't off-hand see one for this case.
I see multiple citations of the requirement that the actual argument be
definable if the dummy has INTENT(INOUT). Thus, for example, you can't
get by with passing a constant or an expression. (Unspecified intent
allows passing an argument that isn't definable as long as that particular
invocation doesn't happen to execute any statements that define the dummy.)
But I can't find a single citation that says the actual argument has to
be defined. Nor do I think there was intended to be such a restriction.
I would consider a compiler that imposed such a restriction to be
non-conforming. If such a dummy argument is then referenced without
first being defined, that would be a violation, but the mere passing
of an undefined actual argument to an INTENT(INOUT) dummy does not violate
any restrictions that I can find. And I'm moderately good at finding
them, although I have been known to miss things in the past. Pertinent
places that I can't find it include (all f95 section numbers) 5.1.2.3
(the prime suspect), 5.2.1 (not much there), 12.5.2.1, and 12.4.1.1
(a section that I've always found hard reading).
If you can find a supporting citation, I'd appreciate hearing about it,
partly because I certainly haven't been making any such assumption in my
own code.
I am not, by the way, interested in hearing about why it should or
should not be some way (at least I'm not interested in that at the moment);
all I'm soliciting is citations about how the standard actually *IS*,
rather than how it should be.
--
Richard Maine
ma...@altair.dfrc.nasa.gov
> Richard Maine wrote in message ...
> ...
> >I am not, by the way, interested in hearing about why it should or
> >should not be some way (at least I'm not interested in that at the moment);
> >all I'm soliciting is citations about how the standard actually *IS*,
> >rather than how it should be.
>
> Well, I am interested in how it should be. In this case, I hope you're
> right about how it is....
In the broader sense, I am also interested in how it should be. I
perhaps overstated that, but I just wanted to emphasize the
distinction so that we didn't end up in one of these usual (for
usenet) confused jumbles where one can't tell what the discussion is
about.... Plus I'm just too busy at the moment for a discussion of
how it should be, but feel I can spare the time to address possible
confusions of how it is (particularly if it turns out that the
confusion is on my part).
--
Richard Maine
ma...@qnet.com
Well, I am interested in how it should be. In this case, I hope you're
right about how it is. I only mentioned it because I actually came across
a case where a compiler refused to allow uninitialized arguments to
be associated with an INOUT dummy. Admittedly, it was one of
the free subset compilers ....
--
J. Giles
Next year, I'll be programming, I dunno, some sort of quantum computer, or
something made of DNA or buckyballs or photons or who knows what. And there'll
be a Fortran compiler for it. :-) But things like extra optimizations and
super-duper run-time checks may not be present in the early versions of the
compiler. Some software companies take a short-sighted view, and only properly
equip their software -especially if it's for an exotic platform- once there's a
sustainable demand for it. If it's an exotic platform, why make an extra
investment in equipping compilers with extra features, an investment that may be
lost if the new platform is unsuccessful commercially?
My point, and Patrick's too, is that we can't expect to always be using a
compiler that provides run-time checking.
[Although, I am intrigued by John's mention of his Fortran Instrumenting tool.
I must look into that. Yes, I will - it seems like a very good idea. I wonder
what the performance hit is?]
> John Appleyard wrote:
[...]
> > I do (really) take your point that compilers exist
> > that make IMPLICIT NONE almost redundant, and one
> > is even free for personal use (but only F77). [...]
I'm really glad to learn that there exist such good
compilers. But, following this thread, I've got an
impression that poeple who promote use of good
compilers _instead of_ IMPLICIT NONE generally ignore
the fact that there are programming environments
where such good compilers aren't an option.
I use a supercomputer, on which you can use virtually
only the single compiler the vendor supplies. You
_could_ install, on your own, a freely available
compiler, but I'm quite sure that runtime efficiency of
the compiled code of such free compilers would be *FAR*
below that of the vendor-supplied one (perhaps a
factor of ten difference?).
("Supercompilers" on supercomputers are such special
beasts.)
So I need to stick to IMPLICIT NONE until virtually
all compilers on major supercomputers acquire comiler
switches that check uninitialized variables.
> What I still remember since
> early 198... is that Occam required exact indentation:
> you will find yourself 'painting' Occam codes with exactly
> two spaces! Is this what you've tried to show us? Great, I said.
Which I find a better solution than free-form a la C or Pascal (ever seen
Tangle's output for the source of tex.pas!?), or all those inconsistently
indented and overly verbose BEGIN...END-type constructions. As I have said
before, programming languages should be (co-)designed by cognitive scientists,
not computer "scientists".
> It reminded, what amazed me at that time, that the transputer
> took 9 processor clock cycles in hardware to evaluate square root.
> I have no idea why just square root was so special for them.
If you have a divide op in hardware, square root comes for free. The
transputer was just the first microprocessor with on-chip FPU, and made
a design decision many (all?) others followed.
> Are you still running transputer in your basement?
Yup. And for the same job, they are still almost as fast as the workstation
on my desk.
> How specifically would occam diagnose mentioned here common
> mistakes which I showed even free Salford compilers crunched
> so effectively rendering annoying like hell implicit none
> rudimental for this purpose?
In occam2, all variables have to be declared, and there is alias and usage
checking, which will catch a lot of these errors.
Jan
> And I've never had it howl where it shouldn't. It works, brilliantly. I find
> it really quite funny that so many people insist it can't possibly work.
It can't possibly work in every instance, apart from hardware tricks. As I
understand Appleyard, it uses a bit pattern stored in memory that are checked
when the variable is read. Consider:
Program Test
Integer:: I
Do I = -HUGE(I) - 1, HUGE(I) ! let's assume two's complement integers
Call AnalyseInteger (I)
EndDo
End Program
How will this not produce a false positive in the called routine?
Jan
> > REAL(4)::abc, answer
> > INTEGER(4)::i
> >
> > abc = 0.
> > DO i=1,10
> > abd = abc + 1. ! "abd" is a misspelling of "abc"
> > END DO
> > answer = abc
[...]
> Here is trace of this error WITHOUT implicit none
>
> *** Variable ABD has been given a value but never used
> 1 ERROR [<main program> FTN95/Win32 v2.00d]
> *** Compilation failed
'scuse me? That was a valid Fortran program. What business does the compiler
have to fail the compilation because a variable was set but never used!?
Jan
To quote an earlier post in this thread...
"Now I know what you're going to say! It is possible to get false
positives using this method. The "undefined" bit pattern may arise in
normal use. This is true, and limits its application to some extent.
However, in practice, false positives are vanishingly rare in 32 bit
variables. I've been using this method more or less daily for a
decade or more (in fact my first exposure to it was in the 70s), and
I think I remember one false positive (but hundreds of genuine ones).
If the risk of false positives really bothers you, a different
implementation is possible; allocate a shadow for every piece of
data, and use bits in the shadow to indicate when bits of the actual
data are set. That gives you single bit resolution, and no false
positives, but at the cost of a doubled memory footprint."
That's true. The compiler default is to treat that condition as a
warning, but the defaults can be changed. In this case it seems to have
been changed from WARNING to ERROR. It could equally have been
suppressed.
Jan Vorbrueggen wrote:
Is 'usage checking' what Saflord Fortran calls 'run-time undefined variables
checking'? I mean, do you find, for example extreemely typical errors like this:
Integer c(5), res, i
implicit none ! with or without this line, whatever
!....
! some program flow which defines array indexes and array values
! simplified up to these statements:
!...
c(1)= 1
c(2)= 2
c(3)= 3
c(4)= 4
c(4)= 5 ! program flow fault or misprint
do i=1,5
res = res+c(i)
enddo
print*,'res=',res
end
---------
John Appleyard wrote:
> In article <y41z5f9...@mailhost.neuroinformatik.ruhr-uni-bochum.de>,
> Jan Vorbrueggen <j...@mailhost.neuroinformatik.ruhr-uni-bochum.de> writes
> >Catherine Rees Lay <Cath...@reeslay.demon.co.uk> writes:
> >
> >> And I've never had it howl where it shouldn't. It works, brilliantly. I find
> >> it really quite funny that so many people insist it can't possibly work.
> >
> >It can't possibly work in every instance, apart from hardware tricks. As I
> >understand Appleyard, it uses a bit pattern stored in memory that are checked
> >when the variable is read. Consider:
> >
> >Program Test
> >
> > Integer:: I
> >
> > Do I = -HUGE(I) - 1, HUGE(I) ! let's assume two's complement integers
> > Call AnalyseInteger (I)
> > EndDo
> >
> >End Program
> >
> >How will this not produce a false positive in the called routine?
> >
> > Jan
>
> To quote an earlier post in this thread...
>
> "Now I know what you're going to say! It is possible to get false
> positives using this method. The "undefined" bit pattern may arise in
> normal use. This is true, and limits its application to some extent.
> However, in practice, false positives are vanishingly rare in 32 bit
> variables. I've been using this method more or less daily for a
> decade or more (in fact my first exposure to it was in the 70s), and
> I think I remember one false positive (but hundreds of genuine ones).
>
Can you reproduce false positive and show it here?
Just interesting.
May be it was just one of compiler bugs in earlier
DOS version?
>
> If the risk of false positives really bothers you, a different
> implementation is possible; allocate a shadow for every piece of
> data, and use bits in the shadow to indicate when bits of the actual
> data are set. That gives you single bit resolution, and no false
> positives, but at the cost of a doubled memory footprint."
> --
Jan's example will do it. Try this.
Do I = -2139062200 , -2139062100
print *,i
EndDo
end
But, in practice, most integers are zero, and most of the rest are 1.
It's also well know that the only negative integer is -9999. :>
John Appleyard wrote:
I supposed you found this for real*8 numbers...
( >30 years of work of Pentium 1GHz :-)
>
> But, in practice, most integers are zero, and most of the rest are 1.
> It's also well know that the only negative integer is -9999. :>
>
You are right.
Do we for example often encounter integer exactly -2139062143
(window handles or color values could be as large as
these integer numbers, but they are usually >-2)
or real*8 exactly -2.1234231234213e-306 ?
Probability is 2**(-32) and 2**(-64) per i or fp number
respectively (sign included).
> > In occam2, all variables have to be declared, and there is alias and usage
> > checking, which will catch a lot of these errors.
> Is 'usage checking' what Saflord Fortran calls 'run-time undefined variables
> checking'?
No, it has to do with not using the same memory location simultaneously in
different parallel threads of execution.
Jan
John Appleyard wrote:
>
[snip]
> But, in practice, most integers are zero, and most of the rest are 1.
It's also well known that for large values of 0 and 1, they are the
same.
> It's also well know that the only negative integer is -9999. :>
>
Dick Hendrickson
Actually, it howls in the caller when it tries to assign the loop
variable. Very clever - you've managed to produce a contrived example
which does something 8 years of real programming hasn't.
I presume you consider this "case closed" and that /undef is therefore
worthless. Happy debugging. I'll let you and the newsgroup know if/when
I hit a false positive in a real program. When I do hit it, I guess I'll
just have live with only having the same tools you do. It's a hard
life...but /undef makes it easier.
> I presume you consider this "case closed" and that /undef is therefore
> worthless.
No, not at all. I'll take any debugging I help I can get, even those (as an
example) that increase the runtime by a factor of 20 or 50. But such tools
aren't for everyday use, IMO, or can be left on for production/shipping
code - in contrast to such things as symbols for good tracebacks and error
messages, or even (optimized) array bounds checking - because they do produce
false positives. I just don't subscribe to the Unix 99% mentality.
Jan
Neither does Catherine, if I recall correctly - she goes for the Windows
95 compromise ...
:-)
--
Toon Moene (to...@moene.indiv.nluug.nl)
Saturnushof 14, 3738 XG Maartensdijk, The Netherlands
Phone: +31 346 214290; Fax: +31 346 214286
GNU Fortran: http://gcc.gnu.org/onlinedocs/g77_news.html
Jan Vorbrueggen wrote:
> Catherine Rees Lay <Cath...@reeslay.demon.co.uk> writes:
>
> > I presume you consider this "case closed" and that /undef is therefore
> > worthless.
>
> No, not at all. I'll take any debugging I help I can get, even those (as an
> example) that increase the runtime by a factor of 20 or 50. But such tools
> aren't for everyday use, IMO, or can be left on for production/shipping
> code - in contrast to such things as symbols for good tracebacks and error
> messages, or even (optimized) array bounds checking - because they do produce
> false positives. I just don't subscribe to the Unix 99% mentality.
>
> Jan
Can't comment seriously after that.
So many snobs in this newsgroup...
They have to stay not married due to
20-80% chance of false positive.