From: JB on 26 May 2010 10:50 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 26 May 2010 11:19 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 26 May 2010 12:44 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 26 May 2010 14:55 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 26 May 2010 15:12
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 |