Optimizing Away

Discussion in 'C Programming' started by jaysome, Nov 15, 2006.

  1. jaysome

    jaysome Guest

    Suppose I have something like this on a free-standing
    environment (where void main(void) is documented and well-defined):

    static int G_num_loops = 0;

    void main (void)
    {
    /* set up interrupts */
    /* ... */
    for ( ; ; )
    {
    G_num_loops++;
    }
    }

    Further suppose that I have the (non-standard) means to "read" the value
    of G_num_loops via a link map and other techniques :)

    Is there anything in the C standard that allows the compiler to
    optimize away and NOT allocate storage for G_num_loops and thus prevent me
    from "viewing" its value? If so, does defining G_num_loops as volatile
    prevent this? (or put in a more standard kind of way, does the C standard
    require the statement:

    G_num_loops++;

    to be executed.

    My compiler seems to be optimizing that statement away when defined as
    static and not volatile. So instead, I change the definition to have
    external linkage:

    int G_num_loops = 0;

    and it works for my purpose.

    The only *potential* problem is that if I define variables with the
    same name (mostly arrays) with external linkage in another translation
    unit (more likely the name would be G_debug_buf), then the linker issues
    an error about multiply defined symbols.

    I can deal with that--I've learned to "work" with the compiler and
    linker and just name such variables with prefixes that are specific to the
    module, e.g., G_fir_debug_buf or G_serial_debug_buf. Maybe I'm just facing
    the reality of embedded debugging, but I'd like to hear the opinions of
    others who have similar experience in this area.

    BTW, the compiler I'm working with does not conform to the C standard in
    that it does not initialize the following file scope definition to 0:

    static int G_num_loops;

    I have to explicitly initialize it to 0:

    static int G_num_loops = 0;

    Thanks
    --
    jay
     
    jaysome, Nov 15, 2006
    #1
    1. Advertising

  2. jaysome

    Richard Bos Guest

    jaysome <> wrote:

    > Suppose I have something like this on a free-standing
    > environment (where void main(void) is documented and well-defined):
    >
    > static int G_num_loops = 0;
    >
    > void main (void)
    > {
    > /* set up interrupts */
    > /* ... */
    > for ( ; ; )
    > {
    > G_num_loops++;
    > }
    > }
    >
    > Further suppose that I have the (non-standard) means to "read" the value
    > of G_num_loops via a link map and other techniques :)
    >
    > Is there anything in the C standard that allows the compiler to
    > optimize away and NOT allocate storage for G_num_loops and thus prevent me
    > from "viewing" its value?


    Yes.

    > If so, does defining G_num_loops as volatile prevent this?


    Keeping in mind that volatile is intentionally under-specified, yes, it
    should.

    > (or put in a more standard kind of way, does the C standard
    > require the statement:
    >
    > G_num_loops++;
    >
    > to be executed.


    No. It requires the program to behave _as if_ it were executed, but if
    there's nothing in the program itself which can detect whether it is, or
    even detect whether G_num_loops exists at all, it's allowed to leave it
    out and only pretend to have increment an int. That you might also be
    able to read its value using means outside the program itself is not
    within the scope of the S Standard, and an implementation is allowed to
    ignore it.

    Making G_num_loops volatile should, as you expect, stop this. All
    accesses of a volatile object must be performed exactly as the Standard
    specifies, with no optimisation performed on it. The catch is that "What
    constitutes an access ... is implementation-defined".
    An implementation could theoretically define an access as any reading of
    a volatile object for the purposes of assigning it to another object, or
    writing a value in it from another object. Since G_num_loops++ involves
    only its own previous and next value, this would not constitute an
    access under such an implementation. That implementation would, however,
    be perverse - strictly within the bounds of the Standard, but perverse -
    and I wouldn't take it into account in practice.

    Richard
     
    Richard Bos, Nov 15, 2006
    #2
    1. Advertising

  3. jaysome

    Guest

    jaysome wrote:
    > Suppose I have something like this on a free-standing
    > environment (where void main(void) is documented and well-defined):
    >
    > static int G_num_loops = 0;
    >
    > void main (void)
    > {
    > /* set up interrupts */
    > /* ... */
    > for ( ; ; )
    > {
    > G_num_loops++;
    > }
    > }
    >
    > Further suppose that I have the (non-standard) means to "read" the value
    > of G_num_loops via a link map and other techniques :)
    >
    > Is there anything in the C standard that allows the compiler to
    > optimize away and NOT allocate storage for G_num_loops and thus prevent me
    > from "viewing" its value? If so, does defining G_num_loops as volatile
    > prevent this? (or put in a more standard kind of way, does the C standard
    > require the statement:
    >
    > G_num_loops++;
    >
    > to be executed.
    >
    > My compiler seems to be optimizing that statement away when defined as
    > static and not volatile. So instead, I change the definition to have
    > external linkage:
    >
    > int G_num_loops = 0;
    >
    > and it works for my purpose.
    >
    > The only *potential* problem is that if I define variables with the
    > same name (mostly arrays) with external linkage in another translation
    > unit (more likely the name would be G_debug_buf), then the linker issues
    > an error about multiply defined symbols.
    >
    > I can deal with that--I've learned to "work" with the compiler and
    > linker and just name such variables with prefixes that are specific to the
    > module, e.g., G_fir_debug_buf or G_serial_debug_buf. Maybe I'm just facing
    > the reality of embedded debugging, but I'd like to hear the opinions of
    > others who have similar experience in this area.
    >
    > BTW, the compiler I'm working with does not conform to the C standard in
    > that it does not initialize the following file scope definition to 0:
    >
    > static int G_num_loops;
    >
    > I have to explicitly initialize it to 0:
    >
    > static int G_num_loops = 0;
    >
    > Thanks
    > --
    > jay


    Defining G_num_loops as volatile will prevent it from being optimized
    out. In embedded applications, you should use the volatile keyword to
    describe any variables that you are mapping to a hardware register.
     
    , Nov 15, 2006
    #3
  4. jaysome

    cassius Guest

    wrote:

    > Defining G_num_loops as volatile will prevent it from being optimized
    > out. In embedded applications, you should use the volatile keyword to
    > describe any variables that you are mapping to a hardware register.


    Right. In addition to hardware registers and memory mapped devices,
    other situations require the use of volatile:

    1) Variables shared between threads.
    2) Variables shared between threads and Interrupt Service routines.
    3) Local variables in functions were setjmp has been called . This is
    an exotic and used in few situations, but worth to mention.
     
    cassius, Nov 15, 2006
    #4
  5. jaysome

    CBFalconer Guest

    jaysome wrote:
    >
    > Suppose I have something like this on a free-standing
    > environment (where void main(void) is documented and well-defined):
    >
    > static int G_num_loops = 0;
    >
    > void main (void)


    Even if it is defined for your peculiar system, why use it? All
    you are doing is creating another needless incompatibility.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>
     
    CBFalconer, Nov 15, 2006
    #5
  6. jaysome

    Tor Rustad Guest

    jaysome wrote:

    > static int G_num_loops = 0;
    >
    > void main (void)
    > {
    > /* set up interrupts */
    > /* ... */
    > for ( ; ; )
    > {
    > G_num_loops++;
    > }
    > }



    In case you are accessing G_num_loops from an
    interrupt handler, I would use:

    volatile static sig_atomic_t G_num_loops;

    volatile will stop the compiler from optimizing away your

    G_num_loops++;

    --
    Tor <torust AT online DOT no>
     
    Tor Rustad, Nov 15, 2006
    #6
  7. CBFalconer <> writes:
    > jaysome wrote:
    >>
    >> Suppose I have something like this on a free-standing
    >> environment (where void main(void) is documented and well-defined):
    >>
    >> static int G_num_loops = 0;
    >>
    >> void main (void)

    >
    > Even if it is defined for your peculiar system, why use it? All
    > you are doing is creating another needless incompatibility.


    A freestanding implementation is free to say that "void main(void)"
    is legal and "int main(void)" isn't. The requirement
    that an implementation must accept "int main(void)" and
    "int main(int argc, char *argv[])" applies *only* to hosted
    environments.

    --
    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, Nov 16, 2006
    #7
  8. jaysome

    jaysome Guest

    On Wed, 15 Nov 2006 17:03:39 -0500, CBFalconer <>
    wrote:

    >jaysome wrote:
    >>
    >> Suppose I have something like this on a free-standing
    >> environment (where void main(void) is documented and well-defined):
    >>
    >> static int G_num_loops = 0;
    >>
    >> void main (void)

    >
    >Even if it is defined for your peculiar system, why use it? All
    >you are doing is creating another needless incompatibility.


    Because if I define main() with a return type of int, and I have
    something like this:

    int main(void)
    {

    for ( ; ; )
    {
    /* do something */
    }

    return 0;
    }

    then some compilers and PC-lint complain about the "return 0;"
    statement being unreachable.

    Using void main(void) is appropriate for most embedded applications
    that I can think of. Furthermore, most embedded applications are
    "incompatible" (which I assume implies "portable") by there very
    nature, so "creating another needless incompatibility" is really a non
    sequitur.

    I prefer to use void main(void) in embedded applications, where it
    makes sense, because my main() will never return, and that's how it's
    designed to work.

    Sometimes it makes sense to shed your pedantic sunglasses when dealing
    with the real world.

    Best regards
    --
    jay
     
    jaysome, Nov 16, 2006
    #8
  9. jaysome

    jaysome Guest

    On 15 Nov 2006 15:24:57 -0800, "Tor Rustad" <>
    wrote:

    >jaysome wrote:
    >
    >> static int G_num_loops = 0;
    >>
    >> void main (void)
    >> {
    >> /* set up interrupts */
    >> /* ... */
    >> for ( ; ; )
    >> {
    >> G_num_loops++;
    >> }
    >> }

    >
    >
    >In case you are accessing G_num_loops from an
    >interrupt handler, I would use:
    >
    >volatile static sig_atomic_t G_num_loops;
    >
    >volatile will stop the compiler from optimizing away your
    >
    >G_num_loops++;


    Tor:

    I think you are correct. Until reading your post I'd never heard of
    the type sig_atomic_t.

    Unfortunately, my compiler does not define the sig_atomic_t type. All
    it has is a comment in <stdint.h>:

    /* sig_atomic_t not defined */

    Thanks
    --
    jay
     
    jaysome, Nov 16, 2006
    #9
  10. jaysome

    CBFalconer Guest

    jaysome wrote:
    >

    .... snip ...
    >
    > I think you are correct. Until reading your post I'd never heard
    > of the type sig_atomic_t.
    >
    > Unfortunately, my compiler does not define the sig_atomic_t type.
    > All it has is a comment in <stdint.h>:
    >
    > /* sig_atomic_t not defined */


    It should be defined in <signal.h>

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>
     
    CBFalconer, Nov 16, 2006
    #10
  11. jaysome

    Tor Rustad Guest

    jaysome wrote:
    >
    > Tor:
    >
    > I think you are correct. Until reading your post I'd never heard of
    > the type sig_atomic_t.


    OK, sig_atomic_t was defined in C89

    > Unfortunately, my compiler does not define the sig_atomic_t type. All
    > it has is a comment in <stdint.h>:
    >
    > /* sig_atomic_t not defined */


    Did you check in <signal.h>?

    --
    Tor <torust AT online DOT no>
     
    Tor Rustad, Nov 16, 2006
    #11
  12. jaysome <> writes:
    > On Wed, 15 Nov 2006 17:03:39 -0500, CBFalconer <>
    > wrote:
    >>jaysome wrote:
    >>>
    >>> Suppose I have something like this on a free-standing
    >>> environment (where void main(void) is documented and well-defined):
    >>>
    >>> static int G_num_loops = 0;
    >>>
    >>> void main (void)

    >>
    >>Even if it is defined for your peculiar system, why use it? All
    >>you are doing is creating another needless incompatibility.

    >
    > Because if I define main() with a return type of int, and I have
    > something like this:
    >
    > int main(void)
    > {
    >
    > for ( ; ; )
    > {
    > /* do something */
    > }
    >
    > return 0;
    > }
    >
    > then some compilers and PC-lint complain about the "return 0;"
    > statement being unreachable.
    >
    > Using void main(void) is appropriate for most embedded applications
    > that I can think of. Furthermore, most embedded applications are
    > "incompatible" (which I assume implies "portable") by there very
    > nature, so "creating another needless incompatibility" is really a non
    > sequitur.
    >
    > I prefer to use void main(void) in embedded applications, where it
    > makes sense, because my main() will never return, and that's how it's
    > designed to work.


    Sure, that makes sense *if* your implementation documents
    "void main(void)" as valid declaration for main.

    If it doesn't, you're risking undefined behavior. Personally, I'd
    rather put up with a warning message than take that risk. YMMV.

    --
    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, Nov 16, 2006
    #12
  13. jaysome

    Tor Rustad Guest

    CBFalconer wrote:
    > jaysome wrote:
    > >
    > > Suppose I have something like this on a free-standing
    > > environment (where void main(void) is documented and well-defined):

    >
    > Even if it is defined for your peculiar system, why use it? All
    > you are doing is creating another needless incompatibility.


    In a freestanding environment, the type (and name!) of
    startup function, is implementation-defined.

    So what (in)compatibility are you talking about?

    --
    Tor <torust AT online DOT no>
     
    Tor Rustad, Nov 16, 2006
    #13
  14. jaysome

    Tor Rustad Guest

    Keith Thompson wrote:
    > jaysome <> writes:
    > > On Wed, 15 Nov 2006 17:03:39 -0500, CBFalconer <>
    > > wrote:
    > >>jaysome wrote:
    > >>>
    > >>> Suppose I have something like this on a free-standing
    > >>> environment (where void main(void) is documented and well-defined)


    [...]

    > Sure, that makes sense *if* your implementation documents
    > "void main(void)" as valid declaration for main.
    >
    > If it doesn't, you're risking undefined behavior. Personally, I'd
    > rather put up with a warning message than take that risk. YMMV.


    What exactly made you beleave OP's implementation might
    not document "void main(void)"?

    :)

    --
    Tor <torust AT online DOT no>
     
    Tor Rustad, Nov 16, 2006
    #14
  15. "Tor Rustad" <> writes:
    > Keith Thompson wrote:
    >> jaysome <> writes:
    >> > On Wed, 15 Nov 2006 17:03:39 -0500, CBFalconer <>
    >> > wrote:
    >> >>jaysome wrote:
    >> >>>
    >> >>> Suppose I have something like this on a free-standing
    >> >>> environment (where void main(void) is documented and well-defined)

    >
    > [...]
    >
    >> Sure, that makes sense *if* your implementation documents
    >> "void main(void)" as valid declaration for main.
    >>
    >> If it doesn't, you're risking undefined behavior. Personally, I'd
    >> rather put up with a warning message than take that risk. YMMV.

    >
    > What exactly made you beleave OP's implementation might
    > not document "void main(void)"?
    >
    > :)


    I believe that it *might* not because I don't know one way or the
    other. For the same reason, I believe that it might.

    (I see the smiley, but I don't get the joke.)

    --
    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, Nov 16, 2006
    #15
  16. Keith Thompson <> wrote:

    (From the OP:)

    > >> >>jaysome wrote:
    > >> >>>
    > >> >>> Suppose I have something like this on a free-standing
    > >> >>> environment (where void main(void) is documented and well-defined)


    > I believe that it *might* not because I don't know one way or the
    > other. For the same reason, I believe that it might.


    OP clearly stated that void main(void) was documented and well-defined
    for his freestanding implementation, leaving little room for doubt.

    --
    C. Benson Manica | I *should* know what I'm talking about - if I
    cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
     
    Christopher Benson-Manica, Nov 16, 2006
    #16
  17. Christopher Benson-Manica <> writes:
    > Keith Thompson <> wrote:
    > (From the OP:)
    >> >> >>jaysome wrote:
    >> >> >>>
    >> >> >>> Suppose I have something like this on a free-standing
    >> >> >>> environment (where void main(void) is documented and well-defined)

    >
    >> I believe that it *might* not because I don't know one way or the
    >> other. For the same reason, I believe that it might.

    >
    > OP clearly stated that void main(void) was documented and well-defined
    > for his freestanding implementation, leaving little room for doubt.


    There's plenty of room for doubt for those of us who don't read
    carefully enough. (*sigh*)

    --
    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, Nov 16, 2006
    #17
  18. On Wed, 15 Nov 2006 23:03:03 -0800, in comp.lang.c , jaysome
    <> wrote:

    >Because if I define main() with a return type of int, and I have
    >something like this:


    (example of a main that never returns)

    >then some compilers and PC-lint complain about the "return 0;"
    >statement being unreachable.


    "When I drive too fast, the oil light comes on.
    So I disconnected the bulb, now it no longer bothers me."

    >Using void main(void) is appropriate for most embedded applications
    >that I can think of.


    Indeed, and this is why the rule is specifically for hosted
    implementations. Furthermore embedded implementations document this as
    an extension.

    --
    Mark McIntyre

    "Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are,
    by definition, not smart enough to debug it."
    --Brian Kernighan
     
    Mark McIntyre, Nov 16, 2006
    #18
  19. jaysome

    Default User Guest

    Keith Thompson wrote:

    > Christopher Benson-Manica <> writes:


    > > OP clearly stated that void main(void) was documented and
    > > well-defined for his freestanding implementation, leaving little
    > > room for doubt.

    >
    > There's plenty of room for doubt for those of us who don't read
    > carefully enough. (*sigh*)



    We gotta start reading the messages now? Damn.




    Brian
     
    Default User, Nov 16, 2006
    #19
  20. "Default User" <> writes:
    > Keith Thompson wrote:
    >> Christopher Benson-Manica <> writes:
    >> > OP clearly stated that void main(void) was documented and
    >> > well-defined for his freestanding implementation, leaving little
    >> > room for doubt.

    >>
    >> There's plenty of room for doubt for those of us who don't read
    >> carefully enough. (*sigh*)

    >
    > We gotta start reading the messages now? Damn.


    No, not at all. We just gotta start reading the messages now.

    --
    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, Nov 16, 2006
    #20
    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. J. Campbell
    Replies:
    4
    Views:
    434
    Stewart Gordon
    Jan 22, 2004
  2. Replies:
    0
    Views:
    303
  3. Replies:
    8
    Views:
    454
  4. Steven D'Aprano

    Optimizing methods away or not?

    Steven D'Aprano, Dec 14, 2008, in forum: Python
    Replies:
    8
    Views:
    257
    Terry Reedy
    Dec 14, 2008
  5. Johannes Schaub (litb)

    Optimizing away an endless loop

    Johannes Schaub (litb), Aug 28, 2010, in forum: C++
    Replies:
    29
    Views:
    783
    cpp4ever
    Sep 10, 2010
Loading...

Share This Page