Nonlocal Store (global and class static variables)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • jose luis fernandez diaz

    Nonlocal Store (global and class static variables)

    Hi,

    I am reading Stroustrup's book 'C++ Programming Language'. In the
    10.4.9 section (Nonlocal Store) he says:

    "A variable defined outside any function (that is global, namespace,
    and class static variables) is initializated (constructed) before main
    is invoked . . ."

    .. . .

    "No implementation-independent guarantees are made about the order of
    construction of nonlocal objects in different complication units . .
    .."

    So this is wrong:

    // foo1.C

    int x = 1;

    // foo2.C

    extern int x;
    int y = x;


    So when I want initializated a global or class static variable with
    other global variable is convenient do it after the main is invoked.

    How can I sure that a global variable is initializated before the main
    is invoked when I am working with different compilation units?

    Thaks,
    Jose Luis.
  • Victor Bazarov

    #2
    Re: Nonlocal Store (global and class static variables)

    "jose luis fernandez diaz" <jose_luis_fdez _diaz_news@yaho o.es> wrote...[color=blue]
    > I am reading Stroustrup's book 'C++ Programming Language'. In the
    > 10.4.9 section (Nonlocal Store) he says:
    >
    > "A variable defined outside any function (that is global, namespace,
    > and class static variables) is initializated (constructed) before main
    > is invoked . . ."
    >
    > . . .
    >
    > "No implementation-independent guarantees are made about the order of
    > construction of nonlocal objects in different complication units . .
    > ."
    >
    > So this is wrong:
    >
    > // foo1.C
    >
    > int x = 1;
    >
    > // foo2.C
    >
    > extern int x;
    > int y = x;[/color]

    It's not wrong. Initialisation with zeroes is done at program loading,
    but it _might_ work as expected. In any case, you have only two possible
    outcomes for the value of 'y': 0 or 1.
    [color=blue]
    > So when I want initializated a global or class static variable with
    > other global variable is convenient do it after the main is invoked.[/color]

    It wouldn't be "initialisation ". It would be "assignment ".
    [color=blue]
    > How can I sure that a global variable is initializated before the main
    > is invoked when I am working with different compilation units?[/color]

    They _are_ initialised _before_ main is invoked. Only the _order_ of
    their initialisation is undefined.

    Put them all in one special compilation unit, "external data".

    Victor


    Comment

    • jose luis fernandez diaz

      #3
      Re: Nonlocal Store (global and class static variables)

      "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message news:<8XpJb.264 117$_M.1243853@ attbi_s54>...[color=blue]
      > "jose luis fernandez diaz" <jose_luis_fdez _diaz_news@yaho o.es> wrote...[color=green]
      > > I am reading Stroustrup's book 'C++ Programming Language'. In the
      > > 10.4.9 section (Nonlocal Store) he says:
      > >
      > > "A variable defined outside any function (that is global, namespace,
      > > and class static variables) is initializated (constructed) before main
      > > is invoked . . ."
      > >
      > > . . .
      > >
      > > "No implementation-independent guarantees are made about the order of
      > > construction of nonlocal objects in different complication units . .
      > > ."
      > >
      > > So this is wrong:
      > >
      > > // foo1.C
      > >
      > > int x = 1;
      > >
      > > // foo2.C
      > >
      > > extern int x;
      > > int y = x;[/color]
      >
      > It's not wrong. Initialisation with zeroes is done at program loading,
      > but it _might_ work as expected. In any case, you have only two possible
      > outcomes for the value of 'y': 0 or 1.
      >[color=green]
      > > So when I want initializated a global or class static variable with
      > > other global variable is convenient do it after the main is invoked.[/color]
      >
      > It wouldn't be "initialisation ". It would be "assignment ".
      >[color=green]
      > > How can I sure that a global variable is initializated before the main
      > > is invoked when I am working with different compilation units?[/color]
      >
      > They _are_ initialised _before_ main is invoked. Only the _order_ of
      > their initialisation is undefined.[/color]

      So, the example above could be wrong because y could be 1 or 0.
      [color=blue]
      >
      > Put them all in one special compilation unit, "external data".[/color]

      Can you give me an example ?. How can I be sure in the example below
      that y is always 1 ?
      [color=blue]
      >
      > Victor[/color]

      Comment

      • Christof Krueger

        #4
        Re: Nonlocal Store (global and class static variables)

        [color=blue][color=green]
        >>Put them all in one special compilation unit, "external data".[/color]
        >
        >
        > Can you give me an example ?. How can I be sure in the example below
        > that y is always 1 ?
        >
        >[color=green]
        >>Victor[/color][/color]
        Within one compilation unit initialisation takes place in the order as
        written in the file.
        So put all your global variables in one cpp-file (or whatever extension
        you prefer)


        // globals.cpp
        int x = 1;
        int y = x;
        <EOF>

        // foo.cpp
        extern int x;
        ....

        // bar.cpp
        extern int y;
        ....


        This way initialisation takes place in globals.cpp in a well defined
        order. Your foo.cpp and bar.cpp files can then use the globals by
        declaring them with the extern keyword.

        --
        Regards,
        Christof Krueger

        Comment

        • jose luis fernandez diaz

          #5
          Re: Nonlocal Store (global and class static variables)

          Christof Krueger <news@pop2wap.n et> wrote in message news:<bt6mo7$d9 d$06$1@news.t-online.com>...[color=blue][color=green][color=darkred]
          > >>Put them all in one special compilation unit, "external data".[/color]
          > >
          > >
          > > Can you give me an example ?. How can I be sure in the example below
          > > that y is always 1 ?
          > >
          > >[color=darkred]
          > >>Victor[/color][/color]
          > Within one compilation unit initialisation takes place in the order as
          > written in the file.
          > So put all your global variables in one cpp-file (or whatever extension
          > you prefer)
          >
          >
          > // globals.cpp
          > int x = 1;
          > int y = x;
          > <EOF>
          >
          > // foo.cpp
          > extern int x;
          > ...
          >
          > // bar.cpp
          > extern int y;
          > ...
          >
          >
          > This way initialisation takes place in globals.cpp in a well defined
          > order. Your foo.cpp and bar.cpp files can then use the globals by
          > declaring them with the extern keyword.[/color]

          Ok, but what if I design a library. How can I force their users to
          initialize the library global variables before their first use ?

          // library.C

          int x = 1;


          // foo1.C

          extern int x;
          int y = x;

          Comment

          • Victor Bazarov

            #6
            Re: Nonlocal Store (global and class static variables)

            "jose luis fernandez diaz" <jose_luis_fdez _diaz_news@yaho o.es> wrote...[color=blue]
            > Christof Krueger <news@pop2wap.n et> wrote in message[/color]
            news:<bt6mo7$d9 d$06$1@news.t-online.com>...[color=blue][color=green][color=darkred]
            > > >>Put them all in one special compilation unit, "external data".
            > > >
            > > >
            > > > Can you give me an example ?. How can I be sure in the example below
            > > > that y is always 1 ?
            > > >
            > > >
            > > >>Victor[/color]
            > > Within one compilation unit initialisation takes place in the order as
            > > written in the file.
            > > So put all your global variables in one cpp-file (or whatever extension
            > > you prefer)
            > >
            > >
            > > // globals.cpp
            > > int x = 1;
            > > int y = x;
            > > <EOF>
            > >
            > > // foo.cpp
            > > extern int x;
            > > ...
            > >
            > > // bar.cpp
            > > extern int y;
            > > ...
            > >
            > >
            > > This way initialisation takes place in globals.cpp in a well defined
            > > order. Your foo.cpp and bar.cpp files can then use the globals by
            > > declaring them with the extern keyword.[/color]
            >
            > Ok, but what if I design a library. How can I force their users to
            > initialize the library global variables before their first use ?
            >
            > // library.C
            >
            > int x = 1;
            >
            >
            > // foo1.C
            >
            > extern int x;
            > int y = x;[/color]

            You cannot force the users of your library to do anything. And,
            to be entirely frank, it's not a good idea to try. Develop your
            library with this thought in mind: the users of it are not dumber
            than you, but they may need a bit of guidance from you. So, do
            supply your library with a good document describing some features
            of your library that are not obvious, or are not features of the
            language.

            If a C++ programmer does not know that objects with static storage
            duration are initialised in unspecified order if they are in two
            different compilation units, it's NOT your problem. Besides, the
            static objects are really best avoided in any C++ program, just
            for that unspecifiedness of the order of their initialisation.

            As to the particular question about how to make 'y' to always be
            the same as 'x', initialise them _BOTH_ from a function:

            // library.C
            int x = functionThatRet urnsXValue();
            int functionThatRet urnsXValue() {
            return 1;
            }

            // foo1.C
            int y = functionThatRet urnsXValue();

            And don't let them see the actual 'x'.

            Victor


            Comment

            • jose luis fernandez diaz

              #7
              Re: Nonlocal Store (global and class static variables)

              "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message news:<HmYJb.731 281$HS4.5490555 @attbi_s01>...[color=blue]
              > "jose luis fernandez diaz" <jose_luis_fdez _diaz_news@yaho o.es> wrote...[color=green]
              > > Christof Krueger <news@pop2wap.n et> wrote in message[/color]
              > news:<bt6mo7$d9 d$06$1@news.t-online.com>...[color=green][color=darkred]
              > > > >>Put them all in one special compilation unit, "external data".
              > > > >
              > > > >
              > > > > Can you give me an example ?. How can I be sure in the example below
              > > > > that y is always 1 ?
              > > > >
              > > > >
              > > > >>Victor
              > > > Within one compilation unit initialisation takes place in the order as
              > > > written in the file.
              > > > So put all your global variables in one cpp-file (or whatever extension
              > > > you prefer)
              > > >
              > > >
              > > > // globals.cpp
              > > > int x = 1;
              > > > int y = x;
              > > > <EOF>
              > > >
              > > > // foo.cpp
              > > > extern int x;
              > > > ...
              > > >
              > > > // bar.cpp
              > > > extern int y;
              > > > ...
              > > >
              > > >
              > > > This way initialisation takes place in globals.cpp in a well defined
              > > > order. Your foo.cpp and bar.cpp files can then use the globals by
              > > > declaring them with the extern keyword.[/color]
              > >
              > > Ok, but what if I design a library. How can I force their users to
              > > initialize the library global variables before their first use ?
              > >
              > > // library.C
              > >
              > > int x = 1;
              > >
              > >
              > > // foo1.C
              > >
              > > extern int x;
              > > int y = x;[/color]
              >
              > You cannot force the users of your library to do anything. And,
              > to be entirely frank, it's not a good idea to try. Develop your
              > library with this thought in mind: the users of it are not dumber
              > than you, but they may need a bit of guidance from you. So, do
              > supply your library with a good document describing some features
              > of your library that are not obvious, or are not features of the
              > language.
              >
              > If a C++ programmer does not know that objects with static storage
              > duration are initialised in unspecified order if they are in two
              > different compilation units, it's NOT your problem. Besides, the
              > static objects are really best avoided in any C++ program, just
              > for that unspecifiedness of the order of their initialisation.
              >
              > As to the particular question about how to make 'y' to always be
              > the same as 'x', initialise them _BOTH_ from a function:
              >
              > // library.C
              > int x = functionThatRet urnsXValue();
              > int functionThatRet urnsXValue() {
              > return 1;
              > }
              >
              > // foo1.C
              > int y = functionThatRet urnsXValue();
              >
              > And don't let them see the actual 'x'.
              >
              > Victor[/color]

              I am agree with you and thank your hints, but sometimes it is necesary
              to use global variables. Stroustup in his book gives an example in
              21.5.2 section (Closing of Streams):

              ". . . how an implementation can ensure that the predefined streams
              cout, cin, cerr and clog are cleated before their first use and closed
              (only) after their last use . . ."

              "The fundamental idea is to define a helper class that is a counter
              that keeps track of how many timesn <iostream> has been included in a
              separately compiled source file:

              class ios_base::Init {
              static int count;
              public:
              Init();
              ~Init();
              };

              namespace { ios_base::Init __ioinit; } // in <iostream>, one copy in
              each file
              // #including <iostream>

              int ios_base::Init: :count=0; // in some .C file

              Each translation unit declares its own object called __ioinit:

              ios_base::Init: :Init() { if (count++==0) { /* initialize cout, cin,
              etc. */}

              ios_base::Init: :~Init(){ if (count--==0) { //clean up cout, cerr . . .
              */ }


              This is a general technique for dealing with libraries that require
              initialization an cleanup of global objects . . ."


              What do you think about this technique ? Do you know another better or
              similar ?

              One can write code like this:

              ostream my_cout=cout;

              #include <iostream>

              but he is a fool if do it.

              I think that the best is follow your hints whenever possible and like
              last resource use a trick similar to the above. What do you think ?

              Regards,
              Jose Luis

              Comment

              • Alf P. Steinbach

                #8
                Re: Nonlocal Store (global and class static variables)

                jose luis fernandez diaz skrev i meldingen ...[color=blue]
                >Hi,
                >
                >I am reading Stroustrup's book 'C++ Programming Language'. In the
                >10.4.9 section (Nonlocal Store) he says:
                >
                >"A variable defined outside any function (that is global, namespace,
                >and class static variables) is initializated (constructed) before main
                >is invoked . . ."
                >
                >. . .
                >
                >"No implementation-independent guarantees are made about the order of
                >construction of nonlocal objects in different complication units . .[/color]

                That is not strictly correct. Variables in a compilation unit U are
                initialized before the first call of a function in U.

                [color=blue]
                >."
                >
                >So this is wrong:
                >
                >// foo1.C
                >
                >int x = 1;
                >
                >// foo2.C
                >
                >extern int x;
                >int y = x;[/color]

                Yes.

                [color=blue]
                >So when I want initializated a global or class static variable with
                >other global variable is convenient do it after the main is invoked.[/color]

                That's one way. But as Victor remarked, it you do that directly it
                would be assignment, not initialization. To get initialization you
                would have to use dynamic allocation or placement new.


                [color=blue]
                >How can I sure that a global variable is initializated before the main
                >is invoked when I am working with different compilation units?[/color]

                Very simple: _don't_ use global variables. Instead, if you absolutely
                must, you can use global accessor functions for non-public variables.
                For example,


                extern Foo& fooInstance()
                {
                static Foo theInstance;
                return theInstance;
                }


                or


                static Foo theInstance;

                extern Foo& fooInstance(){ return theInstance; }


                There are also other solutions.



                Comment

                • Victor Bazarov

                  #9
                  Re: Nonlocal Store (global and class static variables)

                  "jose luis fernandez diaz" <jose_luis_fdez _diaz_news@yaho o.es> wrote...[color=blue]
                  > "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message[/color]
                  news:<HmYJb.731 281$HS4.5490555 @attbi_s01>...[color=blue][color=green]
                  > > "jose luis fernandez diaz" <jose_luis_fdez _diaz_news@yaho o.es> wrote...[color=darkred]
                  > > > Christof Krueger <news@pop2wap.n et> wrote in message[/color]
                  > > news:<bt6mo7$d9 d$06$1@news.t-online.com>...[color=darkred]
                  > > > > >>Put them all in one special compilation unit, "external data".
                  > > > > >
                  > > > > >
                  > > > > > Can you give me an example ?. How can I be sure in the example[/color][/color][/color]
                  below[color=blue][color=green][color=darkred]
                  > > > > > that y is always 1 ?
                  > > > > >
                  > > > > >
                  > > > > >>Victor
                  > > > > Within one compilation unit initialisation takes place in the order[/color][/color][/color]
                  as[color=blue][color=green][color=darkred]
                  > > > > written in the file.
                  > > > > So put all your global variables in one cpp-file (or whatever[/color][/color][/color]
                  extension[color=blue][color=green][color=darkred]
                  > > > > you prefer)
                  > > > >
                  > > > >
                  > > > > // globals.cpp
                  > > > > int x = 1;
                  > > > > int y = x;
                  > > > > <EOF>
                  > > > >
                  > > > > // foo.cpp
                  > > > > extern int x;
                  > > > > ...
                  > > > >
                  > > > > // bar.cpp
                  > > > > extern int y;
                  > > > > ...
                  > > > >
                  > > > >
                  > > > > This way initialisation takes place in globals.cpp in a well defined
                  > > > > order. Your foo.cpp and bar.cpp files can then use the globals by
                  > > > > declaring them with the extern keyword.
                  > > >
                  > > > Ok, but what if I design a library. How can I force their users to
                  > > > initialize the library global variables before their first use ?
                  > > >
                  > > > // library.C
                  > > >
                  > > > int x = 1;
                  > > >
                  > > >
                  > > > // foo1.C
                  > > >
                  > > > extern int x;
                  > > > int y = x;[/color]
                  > >
                  > > You cannot force the users of your library to do anything. And,
                  > > to be entirely frank, it's not a good idea to try. Develop your
                  > > library with this thought in mind: the users of it are not dumber
                  > > than you, but they may need a bit of guidance from you. So, do
                  > > supply your library with a good document describing some features
                  > > of your library that are not obvious, or are not features of the
                  > > language.
                  > >
                  > > If a C++ programmer does not know that objects with static storage
                  > > duration are initialised in unspecified order if they are in two
                  > > different compilation units, it's NOT your problem. Besides, the
                  > > static objects are really best avoided in any C++ program, just
                  > > for that unspecifiedness of the order of their initialisation.
                  > >
                  > > As to the particular question about how to make 'y' to always be
                  > > the same as 'x', initialise them _BOTH_ from a function:
                  > >
                  > > // library.C
                  > > int x = functionThatRet urnsXValue();
                  > > int functionThatRet urnsXValue() {
                  > > return 1;
                  > > }
                  > >
                  > > // foo1.C
                  > > int y = functionThatRet urnsXValue();
                  > >
                  > > And don't let them see the actual 'x'.
                  > >
                  > > Victor[/color]
                  >
                  > I am agree with you and thank your hints, but sometimes it is necesary
                  > to use global variables. Stroustup in his book gives an example in
                  > 21.5.2 section (Closing of Streams):
                  >
                  > ". . . how an implementation can ensure that the predefined streams
                  > cout, cin, cerr and clog are cleated before their first use and closed
                  > (only) after their last use . . ."
                  >
                  > "The fundamental idea is to define a helper class that is a counter
                  > that keeps track of how many timesn <iostream> has been included in a
                  > separately compiled source file:
                  >
                  > class ios_base::Init {
                  > static int count;
                  > public:
                  > Init();
                  > ~Init();
                  > };
                  >
                  > namespace { ios_base::Init __ioinit; } // in <iostream>, one copy in
                  > each file
                  > // #including <iostream>
                  >
                  > int ios_base::Init: :count=0; // in some .C file
                  >
                  > Each translation unit declares its own object called __ioinit:
                  >
                  > ios_base::Init: :Init() { if (count++==0) { /* initialize cout, cin,
                  > etc. */}
                  >
                  > ios_base::Init: :~Init(){ if (count--==0) { //clean up cout, cerr . . .
                  > */ }
                  >
                  >
                  > This is a general technique for dealing with libraries that require
                  > initialization an cleanup of global objects . . ."
                  >
                  >
                  > What do you think about this technique ? Do you know another better or
                  > similar ?[/color]

                  I think it is generally just what the doctor ordered. Believe you me,
                  if it comes from somebody like Dr. Stroustrup, you better listen :-)
                  [color=blue]
                  >
                  > One can write code like this:
                  >
                  > ostream my_cout=cout;[/color]

                  'cout' is undefined here.
                  [color=blue]
                  >
                  > #include <iostream>
                  >
                  > but he is a fool if do it.
                  >
                  > I think that the best is follow your hints whenever possible and like
                  > last resource use a trick similar to the above. What do you think ?[/color]

                  Makes perfect sense to me.

                  Victor


                  Comment

                  Working...