Crazy (?) C problem

Discussion in 'C Programming' started by Jason Sewall, Jan 16, 2005.

  1. Jason Sewall

    Jason Sewall Guest

    Hello,

    I'm using the intel C++ 8.0 compiler on windows and I'm working on some
    software that uses the following lines of code:

    gf->invdim = 1.0/(double)dim;
    printf("invdim: %f\n", (float)gf->invdim);

    dim is an integer, gf->invdim a double. I always get "-1.#IND00" as the
    output of this code, no matter the value of dim, but only at certain
    stages in the code.

    If I duplicate the code like so:

    gf->invdim = 1.0/(double)dim;
    printf("invdim: %f\n", (float)gf->invdim);
    gf->invdim = 1.0/(double)dim;
    printf("invdim: %f\n", (float)gf->invdim);

    The first output is the NAN but the second is the expected result.

    I thought I understood C pretty well, but this is weirding me out.

    I realize that this is grossly out of context but the program is pretty
    complicated and I don't think it would help understand this anyway.

    If anyone here has an insight, I'd be much obliged.

    Jason Sewall
     
    Jason Sewall, Jan 16, 2005
    #1
    1. Advertising

  2. Jason Sewall

    Jason Sewall Guest

    Sorry, here's a quick followup (very quick, I posted the parent just two
    minutes ago).

    I compiled it with intel 8.0 in "Release" mode. No problem. (The problem
    described in parent occured in intel "debug" mode.

    In MSVC 6 Debug, no problem. Ditto for Release.

    There must be some sort of bug in my program that only intel debug
    exposes, a bug in intel, or some weird debug setting that I don't
    understand.

    Anyway, your comments are welcome!

    Jason


    Jason Sewall wrote:
    > Hello,
    >
    > I'm using the intel C++ 8.0 compiler on windows and I'm working on some
    > software that uses the following lines of code:
    >
    > gf->invdim = 1.0/(double)dim;
    > printf("invdim: %f\n", (float)gf->invdim);
    >
    > dim is an integer, gf->invdim a double. I always get "-1.#IND00" as the
    > output of this code, no matter the value of dim, but only at certain
    > stages in the code.
    >
    > If I duplicate the code like so:
    >
    > gf->invdim = 1.0/(double)dim;
    > printf("invdim: %f\n", (float)gf->invdim);
    > gf->invdim = 1.0/(double)dim;
    > printf("invdim: %f\n", (float)gf->invdim);
    >
    > The first output is the NAN but the second is the expected result.
    >
    > I thought I understood C pretty well, but this is weirding me out.
    >
    > I realize that this is grossly out of context but the program is pretty
    > complicated and I don't think it would help understand this anyway.
    >
    > If anyone here has an insight, I'd be much obliged.
    >
    > Jason Sewall
     
    Jason Sewall, Jan 16, 2005
    #2
    1. Advertising

  3. Jason Sewall wrote:
    > Hello,
    >
    > I'm using the intel C++ 8.0 compiler on windows and I'm working on some
    > software that uses the following lines of code:
    >
    > gf->invdim = 1.0/(double)dim;

    ^^^^^^
    pointless cast, the conversion to floating point is triggered by the 1.0
    > printf("invdim: %f\n", (float)gf->invdim);

    ^^^^^^^
    pointless cast. %f is the specifier for a double
     
    Martin Ambuhl, Jan 16, 2005
    #3
  4. Jason Sewall

    infobahn Guest

    Jason Sewall wrote:
    >
    > Hello,
    >
    > I'm using the intel C++ 8.0 compiler on windows and I'm working on some
    > software that uses the following lines of code:
    >
    > gf->invdim = 1.0/(double)dim;
    > printf("invdim: %f\n", (float)gf->invdim);


    The cast is pointless. printf will receive the value as a double anyway.

    > dim is an integer, gf->invdim a double. I always get "-1.#IND00" as the
    > output of this code, no matter the value of dim, but only at certain
    > stages in the code.


    I can see nothing in the code you posted that would provoke such an
    output (unless dim were 0, which I presume you already considered).

    > If anyone here has an insight, I'd be much obliged.


    The problem almost certainly lies elsewhere. I believe that you are
    looking at the bomb's landing site, not its launch site. I wouldn't
    like to speculate on possible causes without seeing the code.
     
    infobahn, Jan 16, 2005
    #4
  5. Jason Sewall

    CBFalconer Guest

    Jason Sewall wrote:
    >

    .... snip ...
    >
    > gf->invdim = 1.0/(double)dim;
    > printf("invdim: %f\n", (float)gf->invdim);


    printf is a variadic function. %f expects a double argument. You
    are casting the argument to a float, thus invoking undefined
    behaviour. I also see no sign of #include <stdio.h>.

    All casts are inherently suspicious.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
     
    CBFalconer, Jan 16, 2005
    #5
  6. CBFalconer wrote:
    > Jason Sewall wrote:
    > >

    > ... snip ...
    > >
    > > gf->invdim = 1.0/(double)dim;
    > > printf("invdim: %f\n", (float)gf->invdim);

    >
    > printf is a variadic function. %f expects a double argument. You
    > are casting the argument to a float, thus invoking undefined
    > behaviour.


    Not directly. It's only undefined behaviour if gf->invdim is not
    representable as a float. The cast will not stop the implicit promotion
    back to double, as per default argument promotions.

    > I also see no sign of #include <stdio.h>.
    >
    > All casts are inherently suspicious.


    --
    Peter
     
    Peter Nilsson, Jan 16, 2005
    #6
  7. CBFalconer <> writes:
    > Jason Sewall wrote:
    >>

    > ... snip ...
    >>
    >> gf->invdim = 1.0/(double)dim;
    >> printf("invdim: %f\n", (float)gf->invdim);

    >
    > printf is a variadic function. %f expects a double argument. You
    > are casting the argument to a float, thus invoking undefined
    > behaviour.


    But the float is then promoted to double.

    > I also see no sign of #include <stdio.h>.


    Or of a main program (it's just a code snippet). But if
    "#include <stdio.h" is missing, you should definitely add it.

    > All casts are inherently suspicious.


    Agreed.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jan 16, 2005
    #7
  8. Jason Sewall

    Jason Sewall Guest

    About the explicit double cast; this has no effect on the code, correct?
    I prefer an explicit cast where possible to eliminate any confusion.

    About the printf formatting: I thought %f expected a float, not a
    double, hence the cast.

    As for comments about including stdio.h, it has been included outside
    the snippet shown here. In fact, there's a whole program around that
    snippet of code. I surprised nobody pointed out that there's no
    declaration of gf or its members, or dim. In fact, there isn't even a
    main() statement!

    The sarcasm is simply to point out that I wanted you all to assume that
    it had those things that every C program does.

    At any rate, the only think I can think of is that I have some
    assignment to a void pointer somewhere that's corrupting the data in the
    program. Whatever, I'll just use the release mode to get the project
    finished. I'll clean up the code later and see if the bug shows up.

    On that note, any suggestions on software for testing for memory leaks
    on windows?

    Thanks,
    Jason

    Keith Thompson wrote:
    > CBFalconer <> writes:
    >
    >>Jason Sewall wrote:
    >>
    >>... snip ...
    >>
    >>>gf->invdim = 1.0/(double)dim;
    >>>printf("invdim: %f\n", (float)gf->invdim);

    >>
    >>printf is a variadic function. %f expects a double argument. You
    >>are casting the argument to a float, thus invoking undefined
    >>behaviour.

    >
    >
    > But the float is then promoted to double.
    >
    >
    >> I also see no sign of #include <stdio.h>.

    >
    >
    > Or of a main program (it's just a code snippet). But if
    > "#include <stdio.h" is missing, you should definitely add it.
    >
    >
    >>All casts are inherently suspicious.

    >
    >
    > Agreed.
    >
     
    Jason Sewall, Jan 16, 2005
    #8
  9. Jason Sewall

    Mike Wahler Guest

    "Jason Sewall" <> wrote in message
    news:41eaa722$...
    > About the explicit double cast;
    > this has no effect on the code, correct?


    It could give incorrect results.
    It could slow it down (but probably not noticeably).

    > I prefer an explicit cast


    casting is explicit by definition.

    > where possible to eliminate any confusion.


    Your code can *cause* confusion by giving a wrong answer.
    It exposes *your* confusion about how C works.

    >
    > About the printf formatting: I thought %f expected a float, not a
    > double, hence the cast.


    Back to the books for you! :)

    (A good 'rule of thumb' (as Chuck alluded) is:
    Treat with suspicion every cast you see and every
    inclination you have to cast).

    Hmm, I feel a .sig coming on...
    "Casts cast suspicion upon the code."

    (Sometimes a cast is indeed the only way to do
    something, but you should be *certain* you
    know what you're doing, and why).

    > As for comments about including stdio.h, it has been included outside
    > the snippet shown here.


    It's always best to post compilable code if at all possible.
    If your code is large, pare it down to a (still compilable)
    example that still reproduces the problem you're asking about.

    >In fact, there's a whole program around that
    > snippet of code. I surprised nobody pointed out that there's no
    > declaration of gf or its members, or dim.


    This means that answers you get are only educated guesses
    and cannot conclusively explain your program's behavior.

    >In fact, there isn't even a
    > main() statement!


    main() is a function, not a statement. Also, a file
    containing compilable C code need not contain a 'main()'
    function at all (most nontrivial C programs are composed
    of many source files, and only one will contain a 'main()'
    function.)

    >
    > The sarcasm


    What sarcasm?

    >is simply to point out that I wanted you all to assume



    Hah!

    > that
    > it had those things that every C program does.


    A huge number of posts here contain code claimed to
    be "C programs" which really are not.

    >
    > At any rate, the only think I can think of is that I have some
    > assignment to a void pointer somewhere that's corrupting the data in the
    > program. Whatever, I'll just use the release mode to get the project
    > finished. I'll clean up the code later and see if the bug shows up.


    Why not actually analyze the problem and really solve it?
    Just guessing will often simply dig you deeper into trouble.
    Do some testing and use your debugger.

    > On that note, any suggestions on software for testing for memory leaks
    > on windows?


    Not topical here. Try a Windows group.

    Finally, please don't top-post in comp.lang.c

    -Mike
     
    Mike Wahler, Jan 16, 2005
    #9
  10. Jason Sewall

    Old Wolf Guest

    Jason Sewall wrote:
    >
    > As for comments about including stdio.h, it has been included
    > outside the snippet shown here. In fact, there's a whole program
    > around that snippet of code. I surprised nobody pointed out that
    > there's no declaration of gf or its members, or dim. In fact,
    > there isn't even a main() statement!


    Nitpick - main() is not a statement (it's a function).

    > The sarcasm is simply to point out that I wanted you all to
    > assume that it had those things


    To assume makes an ASS out of U and ME. It was quite credible
    that your problem was caused by omitting the "#include <stdio.h>"
    (because then printf() would have been declared incorrectly, and
    you had reported problems with printf's behaviour).

    > that every C program does.


    You'd be surprised how many programs don't have those things.

    > At any rate, the only think I can think of is that I have some
    > assignment to a void pointer somewhere that's corrupting the data in

    the
    > program. Whatever,


    Try posting a compilable program that demonstrates the problem.

    > I'll just use the release mode to get the project
    > finished. I'll clean up the code later and see if the bug shows up.


    Most likely, it will show up just when you have to demo the code
    to someone important.
     
    Old Wolf, Jan 16, 2005
    #10
  11. Jason Sewall

    Old Wolf Guest

    Peter Nilsson wrote:
    > CBFalconer wrote:
    > > Jason Sewall wrote:
    > > >

    > > ... snip ...
    > > >
    > > > gf->invdim = 1.0/(double)dim;
    > > > printf("invdim: %f\n", (float)gf->invdim);

    > >
    > > printf is a variadic function. %f expects a double argument. You
    > > are casting the argument to a float, thus invoking undefined
    > > behaviour.

    >
    > Not directly. It's only undefined behaviour if gf->invdim is not
    > representable as a float.


    It's only undefined if gf->invdim is outside the range of float.
    If it is in the range but not representable exactly as float, then
    it must be rounded to one of the two nearest values in an I-D manner
    (that's how I am reading C99, anyway).

    Also, some people have suggested the cast is pointless. It would
    be useful if you wanted to investigate what happened when the
    double in question is rounded to a float (for example, if you had
    noticed strange behaviour when calling a function prototyped
    to take a float parameter).
     
    Old Wolf, Jan 16, 2005
    #11
  12. "Mike Wahler" <> writes:
    > "Jason Sewall" <> wrote in message
    > news:41eaa722$...
    >> About the explicit double cast;
    >> this has no effect on the code, correct?

    >
    > It could give incorrect results.
    > It could slow it down (but probably not noticeably).
    >
    >> I prefer an explicit cast

    >
    > casting is explicit by definition.
    >
    >> where possible to eliminate any confusion.

    >
    > Your code can *cause* confusion by giving a wrong answer.
    > It exposes *your* confusion about how C works.


    That's a little harsh. The original context (lost in the followups)
    was:

    gf->invdim = 1.0/(double)dim;
    printf("invdim: %f\n", (float)gf->invdim);

    where dim is an integer and gv->invdim isa double.

    The constant 1.0 is of type double (as is any unsuffixed floating
    constant), so if the cast is omitted:

    1.0/dim

    the value of dim will be converted to double. The cast, in this
    particular case, is redundant but harmless.

    Casts are inherently suspicious because they do too much, and C has
    enough implicit conversions that casts are usually unnecessary. In
    many cases, a cast tells the compiler "I know what I'm doing; shut up
    and doing what I say" -- which is dangerous if you *don't* know what
    you're doing. The classic example is casting the result of malloc(),
    which can (in C90) mask the error of omitting the "#include <stdlib.h>".

    But casts from one numeric type to another are *relatively* harmless,
    since they convert the value rather than just copying the bits (as
    pointer casts often do).

    Casts are like gotos. They have legitimate uses, but their abuse has
    caused any use of them to be suspicious.

    [...]

    >> As for comments about including stdio.h, it has been included outside
    >> the snippet shown here.


    And we had no way of knowing that.

    > It's always best to post compilable code if at all possible.
    > If your code is large, pare it down to a (still compilable)
    > example that still reproduces the problem you're asking about.


    That's good advice. In fact, in the process of narrowing down your
    code to a small compilable snippet, you'll often solve the problem
    yourself.

    But this case may be one of the rare exceptions. The symptom was
    showing up in a 2-line code snippet. Duplicating that snippet changed
    the symptoms, which didn't make much sense. It might not have been
    possible to narrow down the program while still exhibiting the
    problem.

    [...]

    >> At any rate, the only think I can think of is that I have some
    >> assignment to a void pointer somewhere that's corrupting the data in the
    >> program. Whatever, I'll just use the release mode to get the project
    >> finished. I'll clean up the code later and see if the bug shows up.


    What do you mean by "assignment to a void pointer"? Do you mean a
    null pointer?

    Probably something executed before the snippet you showed us invoked
    undefined behavior and corrupted something somewhere. There are
    numerous things that can cause undefined behavior.

    Compile your code with the highest possible warning and optimization
    levels (higher optization levels cause the compiler to do more
    analysis, which can allow it to detect more errors). Run it under a
    debugger. Examine everything you can, including address and values of
    variables (gf is a pointer; see what address it points to). If
    anything looks odd, trace back in your program and see how it got that
    way.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jan 16, 2005
    #12
  13. Jason Sewall

    Mike Wahler Guest

    "Keith Thompson" <> wrote in message
    news:...
    > "Mike Wahler" <> writes:
    > > "Jason Sewall" <> wrote in message
    > > news:41eaa722$...
    > >> About the explicit double cast;
    > >> this has no effect on the code, correct?

    > >
    > > It could give incorrect results.
    > > It could slow it down (but probably not noticeably).
    > >
    > >> I prefer an explicit cast

    > >
    > > casting is explicit by definition.
    > >
    > >> where possible to eliminate any confusion.

    > >
    > > Your code can *cause* confusion by giving a wrong answer.
    > > It exposes *your* confusion about how C works.

    >
    > That's a little harsh.


    Perhaps. That wasn't my intention.

    > The original context (lost in the followups)
    > was:
    >
    > gf->invdim = 1.0/(double)dim;
    > printf("invdim: %f\n", (float)gf->invdim);
    >
    > where dim is an integer and gv->invdim isa double.
    >
    > The constant 1.0 is of type double (as is any unsuffixed floating
    > constant), so if the cast is omitted:
    >
    > 1.0/dim
    >
    > the value of dim will be converted to double. The cast, in this
    > particular case, is redundant but harmless.


    I was talking about the cast of 'invdim' to 'float'.

    >
    > Casts are inherently suspicious because they do too much, and C has
    > enough implicit conversions that casts are usually unnecessary. In
    > many cases, a cast tells the compiler "I know what I'm doing; shut up
    > and doing what I say" -- which is dangerous if you *don't* know what
    > you're doing.


    In this case (the cast to 'float') I think that is the case.


    > The classic example is casting the result of malloc(),
    > which can (in C90) mask the error of omitting the "#include <stdlib.h>".
    >
    > But casts from one numeric type to another are *relatively* harmless,
    > since they convert the value rather than just copying the bits (as
    > pointer casts often do).


    But my point was that casting a double to a float
    can lose information.

    >
    > Casts are like gotos. They have legitimate uses, but their abuse has
    > caused any use of them to be suspicious.


    Yes.

    >
    > > It's always best to post compilable code if at all possible.
    > > If your code is large, pare it down to a (still compilable)
    > > example that still reproduces the problem you're asking about.

    >
    > That's good advice. In fact, in the process of narrowing down your
    > code to a small compilable snippet, you'll often solve the problem
    > yourself.


    Yes.

    >
    > But this case may be one of the rare exceptions. The symptom was
    > showing up in a 2-line code snippet. Duplicating that snippet changed
    > the symptoms, which didn't make much sense. It might not have been
    > possible to narrow down the program while still exhibiting the
    > problem.


    I was responding to OP's:

    "About the printf formatting: I thought %f expected a float, not a
    double, hence the cast."



    -Mike
     
    Mike Wahler, Jan 17, 2005
    #13
  14. "Mike Wahler" <> writes:
    > "Keith Thompson" <> wrote in message
    > news:...

    [...]
    >> That's a little harsh.

    >
    > Perhaps. That wasn't my intention.
    >
    >> The original context (lost in the followups)
    >> was:
    >>
    >> gf->invdim = 1.0/(double)dim;
    >> printf("invdim: %f\n", (float)gf->invdim);
    >>
    >> where dim is an integer and gv->invdim isa double.
    >>
    >> The constant 1.0 is of type double (as is any unsuffixed floating
    >> constant), so if the cast is omitted:
    >>
    >> 1.0/dim
    >>
    >> the value of dim will be converted to double. The cast, in this
    >> particular case, is redundant but harmless.

    >
    > I was talking about the cast of 'invdim' to 'float'.


    Sorry, I missed that; I thought you were talking about (double)dim.

    The cast to float is also a numeric-to-numeric cast, so it doesn't
    have the same pitfalls that pointer casts can have, but yes, it does
    potentially lose information.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jan 17, 2005
    #14
  15. On Sat, 15 Jan 2005 23:54:39 -0500, Jason Sewall wrote:

    > Sorry, here's a quick followup (very quick, I posted the parent just two
    > minutes ago).
    >
    > I compiled it with intel 8.0 in "Release" mode. No problem. (The problem
    > described in parent occured in intel "debug" mode.
    >
    > In MSVC 6 Debug, no problem. Ditto for Release.
    >
    > There must be some sort of bug in my program that only intel debug
    > exposes, a bug in intel, or some weird debug setting that I don't
    > understand.


    There's nothing obviously wrong in the code you posted. There could easily
    be something wrong in the code you haven't posted which ends up affecting
    the output of this code. You may alternatively have found a genuine
    compiler bug. In order to investigate this further you should create a
    minimal program that demonstrates the problem. That should be easy enough
    to do by cutting down your existing program until just before the point
    where the code works. Hopefully you will then have a program small enough
    to post in its entirety.

    Lawrence
     
    Lawrence Kirby, Jan 17, 2005
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr Newbie

    Crazy Image Problem

    Mr Newbie, Sep 21, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    457
    Mr Newbie
    Sep 22, 2005
  2. JavaEnquirer

    Crazy jar resource access problem

    JavaEnquirer, Feb 22, 2006, in forum: Java
    Replies:
    7
    Views:
    608
    JavaEnquirer
    Feb 27, 2006
  3. Replies:
    3
    Views:
    500
    Steven Kobes
    Jul 27, 2005
  4. Rock Lee

    a crazy problem

    Rock Lee, Jun 29, 2007, in forum: VHDL
    Replies:
    0
    Views:
    683
    Rock Lee
    Jun 29, 2007
  5. Gerry
    Replies:
    6
    Views:
    513
    Gerry
    Feb 7, 2008
Loading...

Share This Page