Question about LCLint warning... 
Author Message
 Question about LCLint warning...

Greetings,

I have the following test program in file z.c:

#include <math.h>

int main(void)
{
  double q1 = 2.0, q2 = 1.0, r_circ;

  r_circ = pow(q1, 3.2) + pow(q2, 1.3);
  return 0;

Quote:
}

I then invoke LCLint and here's the output:

LCLint 2.4b --- 18 Apr 98

z.c: (in function main)
z.c:7:27: Expression has undefined behavior (left operand uses errno, modified
             by right operand): pow(q1, 3.2) + pow(q2, 1.3)
  Code has unspecified behavior. Order of evaluation of function parameters or
  subexpressions is not defined, so if a value is used and modified in
  different places not separated by a sequence point constraining evaluation
  order, then the result of the expression is unspecified. (-evalorder will
  suppress message)
z.c:7:27: Expression has undefined behavior (left operand modifies errno, used
             by right operand): pow(q1, 3.2) + pow(q2, 1.3)

Finished LCLint checking --- 2 code errors found

I am not sure I understand where the problem is. Is it trying to warn me
that whatever value "errno" is set to when pow() is called for the first
time, the second call to pow() will overwrite it? But then why does it say
that left operand *uses* errno?

Saying that an expression is undefined is a strong statement in C, and
because this is happening in a function where I have a "mysterious"
segfault, I am skeptical about this warning; am I missing something?

Thanks,
Christos
--



Wed, 20 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...


Quote:
>I am not sure I understand where the problem is. Is it trying to warn me
>that whatever value "errno" is set to when pow() is called for the first
>time, the second call to pow() will overwrite it?

Yes.

Quote:
> But then why does it say
>that left operand *uses* errno?

Use in computing contexts generally includes access for writing.

Quote:

>Saying that an expression is undefined is a strong statement in C, and
>because this is happening in a function where I have a "mysterious"
>segfault, I am skeptical about this warning; am I missing something?

I too am sceptical about that classification as undefined.  I would be
very disturbed by getting undefined behaviour simply because I used two
floating point math functions in a single expression.  A response to a
DR clarified that sub-expressions must be evaluated (as-if) sequentially
though in any order.

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
--



Thu, 21 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...

Quote:

>I have the following test program in file z.c:

>#include <math.h>

>int main(void)
>{
>  double q1 = 2.0, q2 = 1.0, r_circ;

>  r_circ = pow(q1, 3.2) + pow(q2, 1.3);
>  return 0;
>}

>I then invoke LCLint and here's the output:

>LCLint 2.4b --- 18 Apr 98

>z.c: (in function main)
>z.c:7:27: Expression has undefined behavior (left operand uses errno, modified
>             by right operand): pow(q1, 3.2) + pow(q2, 1.3)
>  Code has unspecified behavior. Order of evaluation of function parameters or
>  subexpressions is not defined, so if a value is used and modified in
>  different places not separated by a sequence point constraining evaluation
>  order, then the result of the expression is unspecified. (-evalorder will
>  suppress message)
>z.c:7:27: Expression has undefined behavior (left operand modifies errno, used
>             by right operand): pow(q1, 3.2) + pow(q2, 1.3)

>Finished LCLint checking --- 2 code errors found

     Wow!  That's picky.  (picky: of or pertaining to doing the job
right.)

Quote:
>I am not sure I understand where the problem is. Is it trying to warn me
>that whatever value "errno" is set to when pow() is called for the first
>time, the second call to pow() will overwrite it? But then why does it say
>that left operand *uses* errno?

>Saying that an expression is undefined is a strong statement in C, and
>because this is happening in a function where I have a "mysterious"
>segfault, I am skeptical about this warning; am I missing something?

     Yes.  You are warned about undefined behavior.  Undefined
behavior can be anything.  For example, it could be mysterious
segfaults.

     Break up the expression so that the two pow() calls aren't
between different evaluation points.

Sincerely,

Gene Wirchenko

Computerese Irregular Verb Conjugation:
     I have preferences.
     You have biases.
     He/She has prejudices.
--



Thu, 21 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...
Well, the big problem is that there is no well-defined "first"
call to pow.  There is a "left" call and a "right" call, but the
compiler is free to make either call "first", then to make
the other one.  To avoid the error, write:

        ...
        double t = pow(q1, 3.2)
        r_circ = t + pow(q2, 1.3);
        ...

Christos Siopis asked about errors in:
    ...

Quote:
>   double q1 = 2.0, q2 = 1.0, r_circ;
>   r_circ = pow(q1, 3.2) + pow(q2, 1.3);

    ...

Quote:
> z.c: (in function main)
> z.c:7:27: Expression has undefined behavior
> (left operand uses errno, modified by right operand):
>     pow(q1, 3.2) + pow(q2, 1.3)
>   Code has unspecified behavior. ...

--



Thu, 21 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...


Quote:
>Well, the big problem is that there is no well-defined "first"
>call to pow.  There is a "left" call and a "right" call, but the
>compiler is free to make either call "first", then to make
>the other one.

So what? How will that change the result?  It might result in different
values stored in errno but that is still not undefined behaviour.

Quote:
> To avoid the error, write:

>       ...
>       double t = pow(q1, 3.2)
>       r_circ = t + pow(q2, 1.3);
>       ...

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
--



Thu, 21 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...


Quote:
>     Break up the expression so that the two pow() calls aren't
>between different evaluation points.

Taking this as you meant it, why?  functions must be evaluated
sequentially and not in parallel so how could multiple writes to errno
be significant (there will be two sequence points, function end and
function start, between writes to it)?

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
--



Thu, 21 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...
Thanks to all who replied... :) A few comments:


Quote:
> However, in
> this case, LCLint is just plain wrong because both bases are positive.  One
> to the 1.3 power is a bit melodramatic, don't you think?  None of my
> business, of course.

> ...

> In this case, why not just write:
>     r_circ = pow(q1, 3.2) + 1.0;
> and that will shut it's mouth.  (Or even precompute q1 to the 3.2 power,
> since that is also a constant).

Well, obviously this was just a test --I tried to replicate the error in a
very simple case before posting it, though I should have probably used a
number other than 1.0 anyway... In the real program, the expressions are
quite more complex.


Quote:
>      Break up the expression so that the two pow() calls aren't
> between different evaluation points.

> To avoid the error, write:

>         double t = pow(q1, 3.2)
>         r_circ = t + pow(q2, 1.3);

Well, I guess that would fix the warning, but IMO it would be a rather
drastic way of dealing with it. I am coding a scientific application with
several calls to math library functions, and if I had to split each
expression in pieces so that no more than one math lib function is
included, the readability would suffer.

My initial guess was that this wasn't a "real" problem (there is so much
science/engineering code out there with multiple math lib function calls
in the same statement!) and I guess your replies confirm this. Granted, if
one wanted to be completely safe, one should check errno after every call
to a math lib function to make sure that no error was produced, but if one
knows in advance that no such error can happen (e.g., because ranges were
checked beforehands) then this is should not be necessary.

The other point is that forgoing such an error check does *not* make the
program undefined, it's just unsafe. So, even though LCLint rightly warned
about this potential problem, I think it should not have labeled it as
"undefined" behavior which, I repeat, is a very strong statement in C!

Thanks again,
Christos
--



Thu, 21 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...

Quote:

> Taking this as you meant it, why?  functions must be evaluated
> sequentially and not in parallel so how could multiple writes to errno
> be significant (there will be two sequence points, function end and
> function start, between writes to it)?

Unless pow() is implemented as a macro.

According to my copy of the C9X draft (I don't have my copy of the C89
standard handy), a call to a library function implemented as a macro
might not contain the sequence points that an actual function call
would.

If the macro implementing pow() updates errno, that's probably what
LCLint is complaining about.  (If it were an actual function call,
LCLint probably wouldn't know -- or care -- that it refers to errno.)

--

San Diego Supercomputer Center           <*>  <http://www.sdsc.edu/~kst>
"Oh my gosh!  You are SO ahead of your time!" -- anon.
--



Fri, 22 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...


Quote:
>Unless pow() is implemented as a macro.

>According to my copy of the C9X draft (I don't have my copy of the C89
>standard handy), a call to a library function implemented as a macro
>might not contain the sequence points that an actual function call
>would.

If that is the case then such macro's would be unusable in much code.  
I do not think you can implement a standard library function as a macro
if the lack of sequence points would cause undefined behaviour.

Quote:

>If the macro implementing pow() updates errno, that's probably what
>LCLint is complaining about.  (If it were an actual function call,
>LCLint probably wouldn't know -- or care -- that it refers to errno.)

>--

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
--



Sun, 24 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...

Quote:

> According to my copy of the C9X draft (I don't have my copy of the C89
> standard handy), a call to a library function implemented as a macro
> might not contain the sequence points that an actual function call
> would.

The C89 standard doesn't seem to include such a statement.  However, I
think it can be derived from the stated rules.  (It's a footnote in
the C9X draft.)

Of course, there are ways to guarantee that calls to pow() are done as
actual function calls, bypassing any macro definitions and
guaranteeing the expected sequence points -- but you wouldn't want to
do that in high-performance code.

--

San Diego Supercomputer Center           <*>  <http://www.sdsc.edu/~kst>
"Oh my gosh!  You are SO ahead of your time!" -- anon.
--



Sun, 24 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...

Quote:



>>Well, the big problem is that there is no well-defined "first"
>>call to pow.  There is a "left" call and a "right" call, but the
>>compiler is free to make either call "first", then to make
>>the other one.

>So what? How will that change the result?  It might result in different
>values stored in errno but that is still not undefined behaviour.

     Sure it is.  You can't tell which one will happen, right?  *That*
makes it undefined.

Quote:
>> To avoid the error, write:

>>       ...
>>       double t = pow(q1, 3.2)
>>       r_circ = t + pow(q2, 1.3);
>>       ...

     ...and sidestep the argument nicely.

Sincerely,

Gene Wirchenko

Computerese Irregular Verb Conjugation:
     I have preferences.
     You have biases.
     He/She has prejudices.
--



Sun, 24 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...

Quote:

>Thanks to all who replied... :) A few comments:

[snip]

Quote:

>> To avoid the error, write:

>>         double t = pow(q1, 3.2)
>>         r_circ = t + pow(q2, 1.3);

>Well, I guess that would fix the warning, but IMO it would be a rather
>drastic way of dealing with it. I am coding a scientific application with
>several calls to math library functions, and if I had to split each
>expression in pieces so that no more than one math lib function is
>included, the readability would suffer.

     For rather small values of "drastic".  First priority, make it
work, then worry about making it nice (where there is a conflict
between the two).

Quote:
>My initial guess was that this wasn't a "real" problem (there is so much
>science/engineering code out there with multiple math lib function calls
>in the same statement!) and I guess your replies confirm this. Granted, if
>one wanted to be completely safe, one should check errno after every call
>to a math lib function to make sure that no error was produced, but if one
>knows in advance that no such error can happen (e.g., because ranges were
>checked beforehands) then this is should not be necessary.

<devil's advocate>
     And because you "know", you can be blindsided rather nicely.
Another system may {*filter*}and who's to say the program will never be
ported?
</devil's advocate>

Quote:
>The other point is that forgoing such an error check does *not* make the
>program undefined, it's just unsafe. So, even though LCLint rightly warned
>about this potential problem, I think it should not have labeled it as
>"undefined" behavior which, I repeat, is a very strong statement in C!

     But it makes the program unpredictable and thus undefined or, at
best, implementation-defined.

     I think paranoia is a wonderful thing in programming.  Paranoid
programmers are the "well-adjusted" ones.

     Two former sigs of mine and a possible future one:

          "'Bugs, Mr. Rico!  Zillions of 'em! ...'"
          -Robert A. Heinlein, "Starship Troopers"

          C Pronunciation Guide:
               y=x++;     "wye equals ex plus plus semicolon"
               x=x++;     "ex equals ex doublecross semicolon"

          Three views of the proverbial partial glass of water:
               Optimist:          half full
               Pessimist:         half empty
               C Programmer:      implementation defined

Sincerely,

Gene Wirchenko

Computerese Irregular Verb Conjugation:
     I have preferences.
     You have biases.
     He/She has prejudices.
--



Sun, 24 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...

Quote:



>>     Break up the expression so that the two pow() calls aren't
>>between different evaluation points.

>Taking this as you meant it, why?  functions must be evaluated

     Evaluation points.

Quote:
>sequentially and not in parallel so how could multiple writes to errno
>be significant (there will be two sequence points, function end and
>function start, between writes to it)?

     Chapter and verse, please.  What stops a compiler from generating
code to do it in parallel?

     I don't know about the two sequence points.  Since *I* don't
know, *I*'d play it cautiously.

Sincerely,

Gene Wirchenko

Computerese Irregular Verb Conjugation:
     I have preferences.
     You have biases.
     He/She has prejudices.
--



Sun, 24 Mar 2002 03:00:00 GMT  
 Question about LCLint warning...

Quote:



> >Unless pow() is implemented as a macro.

> >According to my copy of the C9X draft (I don't have my copy of the C89
> >standard handy), a call to a library function implemented as a macro
> >might not contain the sequence points that an actual function call
> >would.

> If that is the case then such macro's would be unusable in much code.  
> I do not think you can implement a standard library function as a macro
> if the lack of sequence points would cause undefined behaviour.

There doesn't seem to be any such statement in the draft standard.
Should there be?  (Or is it too late?)

--

San Diego Supercomputer Center           <*>  <http://www.sdsc.edu/~kst>
"Oh my gosh!  You are SO ahead of your time!" -- anon.
--



Mon, 25 Mar 2002 03:00:00 GMT  
 
 [ 50 post ]  Go to page: [1] [2] [3] [4]

 Relevant Pages 

1. Question about LCLint warning...

2. A question about Lclint

3. Lclint questions

4. Lclint questions

5. Help required: LCLint should create and use new LCLint libraries...

6. ANSI-C/GCC/LCLINT snprintf() ??

7. LCLint 2.0

8. LcLint environment variable problem (Win95)

9. LCLint installation on HP system

10. LClint initialization problem

11. LCLint doesn't works with new libraries

12. LCLint 2.4 now available

 

 
Powered by phpBB® Forum Software