Home > Archive > Fortran > August 2005 > Undefined array elements
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Undefined array elements
|
|
|
| I would have a small request. This is a short F95 program:
program proba
integer,dimension(8) :: a
a = a(5)
print*, a
endprogram proba
This program will work giving in F or g95 eight integers on the screen
(some random variables depending what was in the memory during
runtime). If there are any possibilities to supress this kind of errors
in F or g95 (array element a(5) used but not defined). I was explained
that there are compiler switches in g95 to force initializing variables
when declared to some definite values (zero, NaN, +inf, -inf). But this
works only for scalars not for arrays. If this is not posible when
declaring I would be satisfied if something will produce some error
message during runtime or any other result indicating that this is
wrong.
Sorry if this issue was posted already. This is my first message to
this group.
Regards
| |
| Herman D. Knoble 2005-08-19, 4:18 pm |
| Windows or Linux Lahey Fortran 95: LF95 -chk (aesux) -chkglobal
The variable (a(5)) has an undefined value.
Error occurs at or near line 3 of _MAIN__
On 19 Aug 2005 07:38:48 -0700, "omorr" <Radovan.Omorjan@gmail.com> wrote:
-|I would have a small request. This is a short F95 program:
-|
-|program proba
-|integer,dimension(8) :: a
-|a = a(5)
-|print*, a
-|endprogram proba
-|
-|This program will work giving in F or g95 eight integers on the screen
-|(some random variables depending what was in the memory during
-|runtime). If there are any possibilities to supress this kind of errors
-|in F or g95 (array element a(5) used but not defined). I was explained
-|that there are compiler switches in g95 to force initializing variables
-|when declared to some definite values (zero, NaN, +inf, -inf). But this
-|works only for scalars not for arrays. If this is not posible when
-|declaring I would be satisfied if something will produce some error
-|message during runtime or any other result indicating that this is
-|wrong.
-|Sorry if this issue was posted already. This is my first message to
-|this group.
-|
-|Regards
| |
| Rich Townsend 2005-08-19, 4:18 pm |
| Herman D. Knoble wrote:
> Windows or Linux Lahey Fortran 95: LF95 -chk (aesux) -chkglobal
On Linux (I can't speak for windows), the single dash should be a double
dash, e.g. --chk instead of -chk.
cheers,
Rich
> The variable (a(5)) has an undefined value.
> Error occurs at or near line 3 of _MAIN__
>
> On 19 Aug 2005 07:38:48 -0700, "omorr" <Radovan.Omorjan@gmail.com> wrote:
>
> -|I would have a small request. This is a short F95 program:
> -|
> -|program proba
> -|integer,dimension(8) :: a
> -|a = a(5)
> -|print*, a
> -|endprogram proba
> -|
> -|This program will work giving in F or g95 eight integers on the screen
> -|(some random variables depending what was in the memory during
> -|runtime). If there are any possibilities to supress this kind of errors
> -|in F or g95 (array element a(5) used but not defined). I was explained
> -|that there are compiler switches in g95 to force initializing variables
> -|when declared to some definite values (zero, NaN, +inf, -inf). But this
> -|works only for scalars not for arrays. If this is not posible when
> -|declaring I would be satisfied if something will produce some error
> -|message during runtime or any other result indicating that this is
> -|wrong.
> -|Sorry if this issue was posted already. This is my first message to
> -|this group.
> -|
> -|Regards
>
| |
| Herman D. Knoble 2005-08-19, 4:18 pm |
| Actually, for diagnosing uninitialized variables the option:
Windows or Linux only the option: --chkglobal
is needed. That is, the double dash works on both platforms.
Skip
On Fri, 19 Aug 2005 11:25:32 -0400, Rich Townsend <rhdt@barVOIDtol.udel.edu> wrote:
-|Herman D. Knoble wrote:
-|> Windows or Linux Lahey Fortran 95: LF95 -chk (aesux) -chkglobal
-|
-|On Linux (I can't speak for windows), the single dash should be a double
-|dash, e.g. --chk instead of -chk.
-|
-|cheers,
-|
-|Rich
-|
-|> The variable (a(5)) has an undefined value.
-|> Error occurs at or near line 3 of _MAIN__
-|>
-|> On 19 Aug 2005 07:38:48 -0700, "omorr" <Radovan.Omorjan@gmail.com> wrote:
-|>
-|> -|I would have a small request. This is a short F95 program:
-|> -|
-|> -|program proba
-|> -|integer,dimension(8) :: a
-|> -|a = a(5)
-|> -|print*, a
-|> -|endprogram proba
-|> -|
-|> -|This program will work giving in F or g95 eight integers on the screen
-|> -|(some random variables depending what was in the memory during
-|> -|runtime). If there are any possibilities to supress this kind of errors
-|> -|in F or g95 (array element a(5) used but not defined). I was explained
-|> -|that there are compiler switches in g95 to force initializing variables
-|> -|when declared to some definite values (zero, NaN, +inf, -inf). But this
-|> -|works only for scalars not for arrays. If this is not posible when
-|> -|declaring I would be satisfied if something will produce some error
-|> -|message during runtime or any other result indicating that this is
-|> -|wrong.
-|> -|Sorry if this issue was posted already. This is my first message to
-|> -|this group.
-|> -|
-|> -|Regards
-|>
| |
| glen herrmannsfeldt 2005-08-22, 3:57 am |
| omorr wrote:
(snip referencing an undefined variable)
> This program will work giving in F or g95 eight integers on the screen
> (some random variables depending what was in the memory during
> runtime). If there are any possibilities to supress this kind of errors
> in F or g95 (array element a(5) used but not defined). I was explained
> that there are compiler switches in g95 to force initializing variables
> when declared to some definite values (zero, NaN, +inf, -inf). But this
> works only for scalars not for arrays. If this is not posible when
> declaring I would be satisfied if something will produce some error
> message during runtime or any other result indicating that this is
> wrong.
I believe that some compilers do static analysis for undefined variables
which can catch many cases. You don't have to try too hard to fool it,
though. Java won't allow anything that fails, including:
if(something) i=1;
else i=2;
is not sufficient to initialize i, even though every programmer
knows that it should be.
For runtime checks, I have known systems to initialize variables
to a specific, rarely used, value and check for that at runtime.
The test fails if you do need that value, not so unusual for
CHARACTER*1 variables.
> Sorry if this issue was posted already. This is my first message to
> this group.
I believe it was recently discussed.
-- glen
| |
| John C. Bollinger 2005-08-23, 7:57 am |
| glen herrmannsfeldt wrote:
> I believe that some compilers do static analysis for undefined variables
> which can catch many cases. You don't have to try too hard to fool it,
> though. Java won't allow anything that fails, including:
>
> if(something) i=1;
> else i=2;
>
> is not sufficient to initialize i, even though every programmer
> knows that it should be.
You are mistaken. The code fragment you present is not a complete,
compilable example, but that style of initialization can be used
successfully in Java. Perhaps you meant something more like this:
if (condition) i = 1;
if (!condition) i = 2;
That one doesn't work in Java, although logically it could, *provided
that "condition" is a local variable*. If "condition" is not local then
there is some chance that its value may be changed from .false. to
..true. by thread B between thread A's execution of the two statements,
thus indeed causing variable "i" to not be initialized. (Note that this
is true of both Fortran and Java, although the latter may more
frequently be used for multithreaded programs.)
It can be even worse: suppose that "condition" is an expression that
invokes an external function. That function might return a different
value on each evaluation, even with the same arguments, so even in the
single-threaded case the style above may not be guaranteed to initialize
"i". Many such cases could conceivably be disambiguated with
sufficiently thorough source analysis, but not all, and one must then
also consider which analyses may be invalidated by changes to other
source files.
The original point was about fooling static analyzers. Java's analyzer
will never miss a possible failure to initialize a variable, but it may
catch some cases that it needn't (though not as many as you may think,
and typically easy to fix). I don't know as much about static analyzers
for Fortran, but I don't immediately see why they shouldn't in principle
be able to do as thorough a job. Am I missing something? If it is true
in practice that static analyzers for Fortran *don't* do as thorough a
job as Java compilers are required to do, then my guess would be that
it's because there is little perceived demand for the feature.
--
John Bollinger
jobollin@indiana.edu
| |
| Arjen Markus 2005-08-23, 7:57 am |
| My guess is that Fortran compilers have traditionally been built with
other emphases, such
as speed and required memory. There are tools around that will do
static analyses in much
the same way as the Java compilers do - Forcheck and ftnchk (or what
are the precise
spellings) for instance.
Another check that is very common in Fortran compilers is the check on
array bounds,
something that can only be done at run-time.
Regards,
Arjen
| |
| Jan Vorbrüggen 2005-08-23, 7:57 am |
| > The original point was about fooling static analyzers. Java's analyzer
> will never miss a possible failure to initialize a variable, but it may
> catch some cases that it needn't (though not as many as you may think,
> and typically easy to fix). I don't know as much about static analyzers
> for Fortran, but I don't immediately see why they shouldn't in principle
> be able to do as thorough a job. Am I missing something?
A large fraction of Fortran code uses arrays in complicated ways. That's
a hard nut to crack competently. The occam2 compiler sported a usage checker
that supported the alias checker for parallel use of memory - but its
implementation on arrays was much too simple minded to work in any useful
code, so I always turned it off.
I suppose that nowwadays, with the memory and processor horsepower available,
one could do a good job of these kinds of analyses. Of course, the point
remains that their job is equivalent to solving the halting problem in the
general case, so you will always have failures of one kind or the other.
Jan
| |
| Gordon Sande 2005-08-23, 7:57 am |
| On 2005-08-23 08:11:57 -0300, "Arjen Markus" <arjen.markus@wldelft.nl> said:
> My guess is that Fortran compilers have traditionally been built with
> other emphases, such
> as speed and required memory. There are tools around that will do
> static analyses in much
> the same way as the Java compilers do - Forcheck and ftnchk (or what
> are the precise
> spellings) for instance.
>
> Another check that is very common in Fortran compilers is the check on
> array bounds,
> something that can only be done at run-time.
There is also the PFORT checker (for Fortran 66) and its equivalent
in the Fortran Tools(?) for hunting down aliasing which could cause
differing results for (nonstandard) programs run under call-by-reference
and copy-in/copy-out semantics.
> Regards,
>
> Arjen
The two systems that have provided run time checks for undefined variables
(undefined in the sense of unknown, invalid, whatever values) were both
from universities where serving large groups of student programmers was
the task at hand and against which they would be judged. The systems are
WatFor (later WatFiv) and Salford. Compile speed was important but
execution was not. (The first student 15 liner is typically not a global
weather model!)
The Lahey/Fujitsu F95 is the exception that proves the rule as this
is a production compiler. The ISS comparison charts that list the
error checking is another exception to the usual benchmark which
is concerned with precisely and only execution speed. The revised
evaluation seems to have real effects as NAG (as of version 5) now
has undefined variable checking. (Without inside knowledge that may
actually reflect the influence of or collaboration with Salford.)
Things have gotten better over time.
A while ago I though I would improve the clarity of a program that
had been working for a long time by reversing the order of two blocks
of code. I did not notice that an initialization statement from the
first block of code was now between the two blocks. A trivial test
run under undefined variable checking caught the fumble fingered
blunder and the fix was in place in minutes. With undefined variable
checking the lapse lasted under five minutes. Without the undefined
variable checking it may have escaped immediate detection and then
taken a lot longer to finally locate.
| |
| Ian Chivers 2005-08-23, 7:00 pm |
| i worked at imperial college on cdc macines in the late 70's
and early 80's.
their fortran compilers had the ability to diagnose the use of undefined
variables.
the developments came from (if i remember correctly)
work done at leicester university and manchester university and
taken on board by cdc.
the traceback gave a snapshot of all variables in each subroutine
and worked back up the call tree.
it required compiling with options to generate a map file
which contained details of the variable layout in memory.
it added about 100 words to the overall size of the executable.
"Gordon Sande" <g.sande@worldnet.att.net> wrote in message
news:2005082309532516807%gsande@worldnet
attnet...
> On 2005-08-23 08:11:57 -0300, "Arjen Markus" <arjen.markus@wldelft.nl>
> said:
>
>
> There is also the PFORT checker (for Fortran 66) and its equivalent
> in the Fortran Tools(?) for hunting down aliasing which could cause
> differing results for (nonstandard) programs run under call-by-reference
> and copy-in/copy-out semantics.
>
>
> The two systems that have provided run time checks for undefined variables
> (undefined in the sense of unknown, invalid, whatever values) were both
> from universities where serving large groups of student programmers was
> the task at hand and against which they would be judged. The systems are
> WatFor (later WatFiv) and Salford. Compile speed was important but
> execution was not. (The first student 15 liner is typically not a global
> weather model!)
>
> The Lahey/Fujitsu F95 is the exception that proves the rule as this
> is a production compiler. The ISS comparison charts that list the
> error checking is another exception to the usual benchmark which
> is concerned with precisely and only execution speed. The revised
> evaluation seems to have real effects as NAG (as of version 5) now
> has undefined variable checking. (Without inside knowledge that may
> actually reflect the influence of or collaboration with Salford.)
>
> Things have gotten better over time.
>
> A while ago I though I would improve the clarity of a program that
> had been working for a long time by reversing the order of two blocks
> of code. I did not notice that an initialization statement from the
> first block of code was now between the two blocks. A trivial test
> run under undefined variable checking caught the fumble fingered
> blunder and the fix was in place in minutes. With undefined variable
> checking the lapse lasted under five minutes. Without the undefined
> variable checking it may have escaped immediate detection and then
> taken a lot longer to finally locate.
>
>
>
>
>
| |
| Gordon Sande 2005-08-23, 7:00 pm |
| On 2005-08-23 12:46:28 -0300, "Ian Chivers" <ian.chivers@ntlworld.com> said:
> i worked at imperial college on cdc macines in the late 70's
> and early 80's.
>
> their fortran compilers had the ability to diagnose the use of undefined
> variables.
>
> the developments came from (if i remember correctly)
> work done at leicester university and manchester university and
> taken on board by cdc.
>
> the traceback gave a snapshot of all variables in each subroutine
> and worked back up the call tree.
>
> it required compiling with options to generate a map file
> which contained details of the variable layout in memory.
>
> it added about 100 words to the overall size of the executable.
>
Good! Another one. I would guess that they initialized things to
a signaling NaN. Too bad more systems do not do such a simple thing.
A long time ago I used ALCOR Algol which had a postmortem facility
which gave the value of every variable on termination. There was
some sort of symbol table mixed in with the object code and a print
program to list everything out. It sure helped figure out why
subscripts went bad.
| |
| glen herrmannsfeldt 2005-08-23, 7:00 pm |
| Gordon Sande wrote:
(snip)
> Good! Another one. I would guess that they initialized things to
> a signaling NaN. Too bad more systems do not do such a simple thing.
It doesn't help for fixed point, but it would seem worth doing.
> A long time ago I used ALCOR Algol which had a postmortem facility
> which gave the value of every variable on termination. There was
> some sort of symbol table mixed in with the object code and a print
> program to list everything out. It sure helped figure out why
> subscripts went bad.
For comparison purposes only, the PL/I equivalent of NAMELIST is called
DATA directed I/O. PUT DATA(I); will print the variable I. If no
I/O list is supplied all variables are used. I do remember doing
GET DATA; I am not sure that I ever tried PUT DATA; It could
result in a LOT of output.
As for Fortran, a NAMELIST WRITE statement just before the end with
an appropriate set of variables would do. I don't know that I
would ever want to see all of them in a program with large,
or even medium sized, arrays.
-- glen
| |
| Gordon Sande 2005-08-23, 7:00 pm |
| On 2005-08-23 16:53:23 -0300, glen herrmannsfeldt <gah@ugcs.caltech.edu> said:
> Gordon Sande wrote:
>
> (snip)
>
>
> It doesn't help for fixed point, but it would seem worth doing.
The machine which was being described did not have fixed point
as integers were just unnormalized floats if I have the CDC
architecture correctly in mind. Thus 48 bit integers on a 60 bit
machine with the most curious integer overflow semantics. ;-)
Your comment is true for other machines. But they do not seem to
readily offer even the half a loaf that might be available.
>
>
> For comparison purposes only, the PL/I equivalent of NAMELIST is called
> DATA directed I/O. PUT DATA(I); will print the variable I. If no
> I/O list is supplied all variables are used. I do remember doing
> GET DATA; I am not sure that I ever tried PUT DATA; It could
> result in a LOT of output.
>
> As for Fortran, a NAMELIST WRITE statement just before the end with
> an appropriate set of variables would do. I don't know that I
> would ever want to see all of them in a program with large,
> or even medium sized, arrays.
If would have to be under control of the nonexistent Fortran
construct of "ON ERROR" to provide an error stop postmortem.
There is not a whole lot if interest in knowing the final
internal state if the program terminated cleanly. Array sizes
are typically kept smaller while debugging is still in progress
so one can tolerate whole arrays being printed, particularly
if it is just to a file. The partial saving grace was that it was
only for routines which were active at the time of error termination
rather than just everything. Algol 60 did not have either NAMELIST
of PUT DATA as it just barely had any I/O at all.
For its time the ALCOR postmortems were rather nice and no equivalent
capability seems to be around at present. Some of the source debuggers
are quite livable but have enough of a learning curve that inserting
a batch of print statements does not look too bad. Particularly if
they are under the control of a debug mode parameter.
>
> -- glen
| |
| Dr Ivan D. Reid 2005-08-24, 6:59 pm |
| On Tue, 23 Aug 2005 20:19:31 GMT, Gordon Sande <g.sande@worldnet.att.net>
wrote in < 2005082317193116807%gsande@worldnetattne
t>:
> The machine which was being described did not have fixed point
> as integers were just unnormalized floats if I have the CDC
> architecture correctly in mind. Thus 48 bit integers on a 60 bit
> machine with the most curious integer overflow semantics. ;-)
Ah! *THAT* might explain the contortions I had to go through to
get five 12-bit integer bytes into one CDC word so as to get 8-bit
paper-tape output from a cross-assembler, to load into a National SC/MP
microprocessor.
--
Ivan Reid, Electronic & Computer Engineering, ___ CMS Collaboration,
Brunel University. Ivan.Reid@[brunel.ac.uk|cern.ch] Room 40-1-B12, CERN
KotPT -- "for stupidity above and beyond the call of duty".
| |
| Bob Lidral 2005-08-29, 7:01 pm |
| Dr Ivan D. Reid wrote:
> On Tue, 23 Aug 2005 20:19:31 GMT, Gordon Sande <g.sande@worldnet.att.net>
> wrote in < 2005082317193116807%gsande@worldnetattne
t>:
>
>
>
>
> Ah! *THAT* might explain the contortions I had to go through to
> get five 12-bit integer bytes into one CDC word so as to get 8-bit
> paper-tape output from a cross-assembler, to load into a National SC/MP
> microprocessor.
>
The two are probably unrelated.
The CDC CYBER binary floating point representation was defined as
follows (from memory, so please be kind when correcting me):
One's complement; sign in high-order bit, significant bits of value
in low-order 48 (I believe) bits; all significant bits were
represented explicitly unlike the current IEEE standard.
Implied binary point at the low-order end of the word (rather than
at the high-order end as with most other implementations). This was
their version of "normalized".
11-bit binary exponent (as opposed to IBM's hexadecimal exponent)
field biased such that an all-zero exponent field meant a zero
exponent value -- and, hence, an integral value.
This resulted in the feature that the machine representation for an
integer was the same in floating-point format as in fixed-point format,
provided the integer was small enough (representable in 49 bits, 48 bits
plus the sign).
It's not true that there weren't integers. The hardware did integer
addition and subtraction for both the 60-bit (X) and 18-bit (A and B)
registers. But they didn't have integer multiplication and division;
that was done in the floating point hardware for 60-bit (X) registers only.
I'm not sure why you needed to get 5 12-bit "bytes" into a 60-bit word;
the CDC CYBERs used 6-bit characters packed 10 to a word. However, the
Peripheral Processors (PPs) which did all the I/O and in which much of
the operating system executed, were 12-bit machines (except that their
accumulator register was 18 bits). Data was transferred in 12-bit
chunks while the CPU used 18-bit addresses (well, until extended memory
was added increasing the address space to 21- and/or 24-bit
addressability, I forget which). So the machine used to pack and unpack
12-bit fields to and from 60 bit words. This required the PPs to do
multiplication and division by 5; multiply-by-5 was relatively easy
(shift and add) but divide-by-five without a loop on a 12-bit machine
(with 18-bit accumulator) without a division instruction was challenging
(and extremely cleverly done).
But all of that was usually hidden from the users so I'm not sure why
you had to be aware of it. Unless you were converting 8-bit characters
to 12-bit before packing them into a 60-bit word? In any case, packing
12-bit bytes into a 60-bit CDC word using CDC's FORTRAN shouldn't have
been very difficult (use shift-and-add or shift-and-or -- CDC FORTRAN
had shift operations) -- unless you tried to do it using multiply-and-add?
Computer cards (at least the IBM-compatible ones; for this discussion we
can ignore the Univac dual-row, 90-column, round-hole cards) had 12
rows, or 12 bits per column, and 7-track (6 bits plus a parity bit)
magnetic tapes were common in the early days of CYBERs, so that may be
why data was transferred in 12-bit chunks. That may also have
influenced the choice of a 60-bit word (even multiple of 12, which 64 is
not).
Just for fun, while IBM used BCD and EBCDIC character encodings and many
other vendors chose ASCII, CDC had its own character encoding called
"Display Code". One interesting, and perhaps perverse :-), "feature" of
this character set was that 1s-complement addition or subtraction of two
words containing characters representing decimal digits resulted in a
word containing characters representing the 9s-complement of the
corresponding decimal result. I don't know whether any compilers took
advantage of this (it might have been useful for COBOL).
Bob Lidral
lidral at alum dot mit dot edu
| |
| Dr Ivan D. Reid 2005-08-30, 3:56 am |
| On Mon, 29 Aug 2005 11:32:34 -0400, Bob Lidral <l1dralspamba1t@comcast.net>
wrote in <L92dnZDdh-hDt47eRVn-sg@comcast.com>:
> Dr Ivan D. Reid wrote:
[color=darkred]
[color=darkred]
[color=darkred]
> I'm not sure why you needed to get 5 12-bit "bytes" into a 60-bit word;
> the CDC CYBERs used 6-bit characters packed 10 to a word. However, the
> Peripheral Processors (PPs) which did all the I/O and in which much of
> the operating system executed, were 12-bit machines (except that their
> accumulator register was 18 bits). Data was transferred in 12-bit
> chunks while the CPU used 18-bit addresses (well, until extended memory
> was added increasing the address space to 21- and/or 24-bit
> addressability, I forget which). So the machine used to pack and unpack
> 12-bit fields to and from 60 bit words. This required the PPs to do
> multiplication and division by 5; multiply-by-5 was relatively easy
> (shift and add) but divide-by-five without a loop on a 12-bit machine
> (with 18-bit accumulator) without a division instruction was challenging
> (and extremely cleverly done).
> But all of that was usually hidden from the users so I'm not sure why
> you had to be aware of it. Unless you were converting 8-bit characters
> to 12-bit before packing them into a 60-bit word? In any case, packing
> 12-bit bytes into a 60-bit CDC word using CDC's FORTRAN shouldn't have
> been very difficult (use shift-and-add or shift-and-or -- CDC FORTRAN
> had shift operations) -- unless you tried to do it using multiply-and-add?
Much of what you say rings true. I made various incremental
discoveries along the way of trying to get a National Semiconductor
cross-assembler running on the Adelaide Cyber to produce 8-hole paper tape
to load into the SC/MP development system where it was blown into EPROMS
to be used in the final hardware. Most of the solutions were found by
poring through the FORTRAN manual and probably some OS manuals -- the
consulting staff were at a total loss. I found out about the 12-bit
output and that I had to pad the 8-bit binary code into those bytes. Then
there was the fact that multiplication only worked up to 48 bits so I had
to use successive adds to shift the first four bytes along to add in the
fifth. Then the output would mysteriously die mid-tape, and after some
puzzling I discovered that an all-zero 12-bit byte was taken as
end-of-file (IIRC, or was it two in succession?) so I changed to making
the four MSBs in each byte all ones so that NULLs weren't misinterpreted as
EOF. ...and then it ran happily ever after and my development of software
for the Mawson Antarctic Interferometer became much easier (I'd done the
periscope control by hand, including keying in the code; coding the other
three processors was much quicker even though they were considerably more
complicated).
--
Ivan Reid, Electronic & Computer Engineering, ___ CMS Collaboration,
Brunel University. Ivan.Reid@[brunel.ac.uk|cern.ch] Room 40-1-B12, CERN
KotPT -- "for stupidity above and beyond the call of duty".
|
|
|
|
|