From: JB on
On 2010-05-26, Gordon Sande <Gordon.Sande(a)gmail.com> wrote:
> There are various "definitions" of undefined. Many are so watered down
> that it takes a skilled lawyer to show why they are not fraudulent. If
> you don't notice the distinctions you can be fooled into treating them as
> all the same.

Fascinating. Can you provide some example of such fraudulent
definitions in common use?

> The useful definition is that the variable has never been assigned a value
> by the user after the variable has come into existence. The descriptions
> of Valgrind I have seen to not include such a capability.

Would you say that the following example constitutes detection of an
uninitialized variable, or what is it?

program vt
integer :: ii
print *, ii
end program vt

$ valgrind --track-origins=yes ./a.out
==27324== Memcheck, a memory error detector
==27324== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==27324== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==27324== Command: ./a.out
==27324==
==27324== Conditional jump or move depends on uninitialised value(s)
==27324== at 0x4C526F5: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==27324== by 0x4CFD144: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==27324== by 0x4D006DE: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==27324== by 0x40076B: MAIN__ (vt.f90:3)
==27324== by 0x4007A9: main (in /home/job/src/valgrindtest/a.out)
==27324== Uninitialised value was created by a stack allocation
==27324== at 0x400711: MAIN__ (vt.f90:1)
....

valgrind is not that good at detecting stack allocations; as you can
see, it only gives the line where the procedure starts, not which
variable is guilty. Heap detection is generally better, and usually at
least, gives directly the line where the error occurs and where the
variable was declared. (The ???'s are because for some reason
libgfortran was not compiled with debug symbols included)

And, as I mentioned in my previous message, if the ii variable is made
SAVE, then valgrind won't detect it, as the compiler sets it to 0, and
valgrind in it's somewhat C-centric worldview thinks everything is ok.

> If it does have
> such a capability I would like to see a reference to it. Undefined variable
> checking requires either hardware assistance (parity checking is quick, easy
> and effective when possible) or much checking of all accessed values by the
> running program (which means that the object code is bulky and slowed in the
> several implementations I have seen) as a result of the compiler inserting
> the extra checking. Valgrind does not seem to benefit from either mode.

AFAIK valgrind functions, in a way, like a simulator. Valgrind takes
the object code and inserts the profiling or instrumentation code on
the fly. And yes, it's slow - but presumably, so are the uninitialized
variable tracking, bounds checking etc. code inserted by some
compilers, at least Lahey was when I last used it.

> Another area when the "definitions" are slippery is execution profiling.
> Some systems give exact line by line counts of the execution history
> as a result of extensive instrumentation. Others give a sampling of the
> location of the location counter with the association to the source done
> by looking at the loading map of the program. Same definition but such
> greatly different capabilities that one wonders how the same name can be
> justified. Valgrind offers sampling. Marketing!

Ok. IMHO, instrumentation and sampling based profiling are useful for
different, although to some extent overlapping, purposes, and both
are, well, again IMHO, clearly profiling.


--
JB
From: Gordon Sande on
On 2010-05-26 11:50:56 -0300, JB <foo(a)bar.invalid> said:

> On 2010-05-26, Gordon Sande <Gordon.Sande(a)gmail.com> wrote:
>> There are various "definitions" of undefined. Many are so watered down
>> that it takes a skilled lawyer to show why they are not fraudulent. If
>> you don't notice the distinctions you can be fooled into treating them as
>> all the same.
>
> Fascinating. Can you provide some example of such fraudulent
> definitions in common use?
>
>> The useful definition is that the variable has never been assigned a value
>> by the user after the variable has come into existence. The descriptions
>> of Valgrind I have seen to not include such a capability.
>
> Would you say that the following example constitutes detection of an
> uninitialized variable, or what is it?
>
> program vt
> integer :: ii
> print *, ii
> end program vt
>
> $ valgrind --track-origins=yes ./a.out
> ==27324== Memcheck, a memory error detector
> ==27324== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
> ==27324== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
> ==27324== Command: ./a.out
> ==27324==
> ==27324== Conditional jump or move depends on uninitialised value(s)
> ==27324== at 0x4C526F5: ??? (in /usr/lib64/libgfortran.so.3.0.0)
> ==27324== by 0x4CFD144: ??? (in /usr/lib64/libgfortran.so.3.0.0)
> ==27324== by 0x4D006DE: ??? (in /usr/lib64/libgfortran.so.3.0.0)
> ==27324== by 0x40076B: MAIN__ (vt.f90:3)
> ==27324== by 0x4007A9: main (in /home/job/src/valgrindtest/a.out)
> ==27324== Uninitialised value was created by a stack allocation
> ==27324== at 0x400711: MAIN__ (vt.f90:1)
> ...
>
> valgrind is not that good at detecting stack allocations; as you can
> see, it only gives the line where the procedure starts, not which
> variable is guilty. Heap detection is generally better, and usually at
> least, gives directly the line where the error occurs and where the
> variable was declared. (The ???'s are because for some reason
> libgfortran was not compiled with debug symbols included)
>
> And, as I mentioned in my previous message, if the ii variable is made
> SAVE, then valgrind won't detect it, as the compiler sets it to 0, and
> valgrind in it's somewhat C-centric worldview thinks everything is ok.

A rather watered down defintion of detecting an undefined variable. Simple
flow analysis yields this as an uninitialized variable for many compilers.
Are you sure you didn't take at least first year law school if that is
your example of useful undefined variable checking? ;-)

Try something like setting the 1st and 3rd element of an array and referecing
the 2nd element. And make these subscript values data values so there
can be no static analysis. The systems I gave (but you snipped) all will find
that the 2nd element is undefined. Lahey will miss it for allocated arrays if
I recall their list of restrictions. They would seem to miss setting
the sentinel
value. Funny lapse, maybe cured by now as it has been a while since I
used them.

>> If it does have
>> such a capability I would like to see a reference to it. Undefined variable
>> checking requires either hardware assistance (parity checking is quick, easy
>> and effective when possible) or much checking of all accessed values by the
>> running program (which means that the object code is bulky and slowed in the
>> several implementations I have seen) as a result of the compiler inserting
>> the extra checking. Valgrind does not seem to benefit from either mode.
>
> AFAIK valgrind functions, in a way, like a simulator. Valgrind takes
> the object code and inserts the profiling or instrumentation code on
> the fly. And yes, it's slow - but presumably, so are the uninitialized
> variable tracking, bounds checking etc. code inserted by some
> compilers, at least Lahey was when I last used it.
>
>> Another area when the "definitions" are slippery is execution profiling.
>> Some systems give exact line by line counts of the execution history
>> as a result of extensive instrumentation. Others give a sampling of the
>> location of the location counter with the association to the source done
>> by looking at the loading map of the program. Same definition but such
>> greatly different capabilities that one wonders how the same name can be
>> justified. Valgrind offers sampling. Marketing!
>
> Ok. IMHO, instrumentation and sampling based profiling are useful for
> different, although to some extent overlapping, purposes, and both
> are, well, again IMHO, clearly profiling.

And one is rather thin gruel if you are expecting the real thing. All too
often it is sold at the real thing by those who just see the single word.

There is a common rule for safety (or security) that partial weak protection
is often worse than none as it leads to carelessness. Something similar
applies to debugging tools. Weak ones allow check boxes to be checked but
do not find that many bugs.




From: Steven Correll on
On May 25, 1:06 pm, Paul van Delst <paul.vande...(a)noaa.gov> wrote:
> Can some kind, patient person explain exactly what the use of static memory entails? For
> example, if one uses the "-fstatic" option for a compiler.
>
> A colleague is having an issue with some code that runs fine on one machine (#1: redhat 4,
> 32 bit, g95 v4.0), but bombs on another (#2: redhat 3, 32 bit, g95 v4.1). And by bombs I
> mean it runs to completion, but the results are full of NaN's.
>
> One of the debug suggestions I made was to *remove* the "-fstatic" switch from the
> compile. When she did that the runs bombed on both machines. She asked me why that would
> happen...

With the g95 compiler, -fstatic does refer to static allocation (as
opposed to -static, which refers to static linking.) As other posters
have said, this can change the behavior of a program because (a) on a
Red Hat Linux system, uninitialized local static variables have the
value zero when the program loads, whereas uninitialized stack-
allocated variables have values that depend on whatever happened to
use that part of the stack previously; and (b) on the n'th call to a
procedure, a local static variable will retain the value it had when
the n-1'th call returned. I'd like to add a third reason: (c) with
static allocation, most compilers tend to put variables from
procedures A and B nearby in memory if A and B are nearby in the
source file, whereas with stack allocation, variables from A and B
tend to be nearby if A calls B or vice versa, even if A and B are not
nearby in the source.

That means the effect of storing outside the bounds of an array can be
very different with static vs stack allocation, because the "victim"
of the illegal store is apt to be a different variable. In one case,
the "victim" may be unharmed because it belongs to a procedure which
hasn't yet been called and which will correct the problem by setting
the "victim" to the right value before using it; in the other case,
the "victim" may be a variable whose value has already been set, and
which is about to be used by code which will react unpleasantly to
unexpected changes to that value.

Whether the behavior you're observing is (a), (b), or (c), of course
all the usual tactics apply: methodically initialize variables, use
tools or compiler options to report uninitialized variables, and use
options to check bounds at runtime. Good luck!
From: JB on
On 2010-05-26, Gordon Sande <Gordon.Sande(a)gmail.com> wrote:
> On 2010-05-26 11:50:56 -0300, JB <foo(a)bar.invalid> said:
>
>> On 2010-05-26, Gordon Sande <Gordon.Sande(a)gmail.com> wrote:
>>> The useful definition is that the variable has never been assigned a value
>>> by the user after the variable has come into existence. The descriptions
>>> of Valgrind I have seen to not include such a capability.
>>
>> Would you say that the following example constitutes detection of an
>> uninitialized variable, or what is it?
>>
>> program vt
>> integer :: ii
>> print *, ii
>> end program vt
>>
>> $ valgrind --track-origins=yes ./a.out
>> ==27324== Memcheck, a memory error detector
>> ==27324== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
>> ==27324== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
>> ==27324== Command: ./a.out
>> ==27324==
>> ==27324== Conditional jump or move depends on uninitialised value(s)
>> ==27324== at 0x4C526F5: ??? (in /usr/lib64/libgfortran.so.3.0.0)
>> ==27324== by 0x4CFD144: ??? (in /usr/lib64/libgfortran.so.3.0.0)
>> ==27324== by 0x4D006DE: ??? (in /usr/lib64/libgfortran.so.3.0.0)
>> ==27324== by 0x40076B: MAIN__ (vt.f90:3)
>> ==27324== by 0x4007A9: main (in /home/job/src/valgrindtest/a.out)
>> ==27324== Uninitialised value was created by a stack allocation
>> ==27324== at 0x400711: MAIN__ (vt.f90:1)
>> ...
>>
>> valgrind is not that good at detecting stack allocations; as you can
>> see, it only gives the line where the procedure starts, not which
>> variable is guilty. Heap detection is generally better, and usually at
>> least, gives directly the line where the error occurs and where the
>> variable was declared. (The ???'s are because for some reason
>> libgfortran was not compiled with debug symbols included)
>>
>> And, as I mentioned in my previous message, if the ii variable is made
>> SAVE, then valgrind won't detect it, as the compiler sets it to 0, and
>> valgrind in it's somewhat C-centric worldview thinks everything is ok.
>
> A rather watered down defintion of detecting an undefined variable.

How come? You yourself provided a defition for detecting undefined
variables as "The useful definition is that the variable has never
been assigned a value by the user after the variable has come into
existence". Then you claimed that valgrind cannot detect such errors
"The descriptions of Valgrind I have seen to not include such a
capability.". And then I provided a trivial counterexample where
valgrind was indeed able to detect such a use of an undefined
variable.

Seems like you're trying to sucker me into a game of moving the
goalposts.

> Simple
> flow analysis yields this as an uninitialized variable for many compilers.

Yes. What does that have to do with valgrind?

> Are you sure you didn't take at least first year law school

No, I didn't. I once had a girlfriend who was studying law, though, in
case you feel that's somehow pertinent to the argument.

> if that is
> your example of useful undefined variable checking? ;-)

Well, the example wasn't intented to show the limits of what valgrind
is capable of, just that contrary to previous claims, it can indeed
detect use of uninitialized variables.

I have successfully used valgrind to find uses of uninitialized
variables, and other common memory errors that I myself, and others,
have made, so yes, I find it useful, despite it perhaps never
fulfilling some yet to be heard criteria for perfection.

> Try something like setting the 1st and 3rd element of an array and referecing
> the 2nd element. And make these subscript values data values so there
> can be no static analysis. The systems I gave (but you snipped) all will find
> that the 2nd element is undefined.

I sort of fear that a testcase I do myself will, like my previous one,
not be up to your high standards, so why don't you provide the code
that I can test since you already seem to have it?

>> Ok. IMHO, instrumentation and sampling based profiling are useful for
>> different, although to some extent overlapping, purposes, and both
>> are, well, again IMHO, clearly profiling.
>
> And one is rather thin gruel if you are expecting the real thing.

Yes, I tried to imply that with my comment that they are useful for
different purposes (assuming here that the "real thing" refers to the
profiling approach more appropriate for the task at hand).

--
JB
From: Richard Maine on
Gordon Sande <Gordon.Sande(a)gmail.com> wrote:

> There are various "definitions" of undefined. Many are so watered down
> that it takes a skilled lawyer to show why they are not fraudulent. If
> you don't notice the distinctions you can be fooled into treating them as
> all the same.
>
> The useful definition is that the variable has never been assigned a value
> by the user after the variable has come into existence.

There is also the definition in the Fortran standard. That one probably
falls into the category of taking a skilled lawyer, but it is one that
is particularly relevant to Fortran. Note that it is not particularly
close to the same definition as the one you refer to above as "the
useful definition." For example, the f2003 standard lists 18 ways for a
variable to become undefined, and some of those 18 ways include multiple
subitems, so that the list might plausibly said to have about 30 ways.

Yes, it takes a language lawyer to read some of them, but others are
pretty important and useful to know. People get bit by several of them,
sometimes even when the people do know the rules and violate them by
accident. That's happened to me. I'm thinking of a case where I
accidentally declared a dummy argument to be intent(out), which made the
actual argument become undefined, even if it had been previously
defined. That code worked for several years until a new version of the
compiler behaved differently from the version I had been using.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain