Can I rely on a function-scoped static variable for a method called during program shutdown?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite












Quick context: I'm seeing errors on program shutdown, that stem from dependencies between global members (::sigh::, I know, I know). One global variable's destructor might refer to another global -- and if that one's already been destructed, things get bad.



But here's a particular case where I just don't know whether behavior is well-defined: a static variable inside a function. Can I rely on the function behaving consistently even during program shutdown? Or is it possible that the static member will be destroyed, and the function will run anyway, without creating a new one?



Here's a toy example demonstrating what I'm interested in:



class Logger

public:
enum class Severity DEBUG, INFO, WARNING, ERROR ;
void Log(Severity sev, const std::string& msg)

LogImpl(FormatMessage(sev, msg));


Logger() Log(Severity::INFO, "Logger active");
~Logger() Log(Severity::INFO, "Logger inactive");

protected:
static std::string FormatMessage(Severity sev, const std::string& msg)

static const std::map<Severity, std::string> enum2str
Severity::DEBUG, "DEBUG",
Severity::INFO, "INFO",
Severity::WARNING, "WARNING",
Severity::ERROR, "ERROR"
;

// Throws or crashes if enum2str is invalid, or uninitialized:
return "[" + enum2str[sev] + "] " + msg;

void LogImpl(const std::string& msg)

std::cout << msg << std::endl;

;


Let's imagine I have a global instance of Logger. The enum2str map in Logger::FormatMessage is a static variable, so at some point during program shutdown, it will be destroyed.



By standard, can this cause my program to crash on shutdown? Is enum2str inherently unreliable during shutdown? Or is there some handling of this -- for example, if enum2str is invalid at some point, perhaps a new static instance will be created?



(I am not interested in relying on destruction order between objects, e.g. where I declare the global Logger instance.)










share|improve this question

























    up vote
    6
    down vote

    favorite












    Quick context: I'm seeing errors on program shutdown, that stem from dependencies between global members (::sigh::, I know, I know). One global variable's destructor might refer to another global -- and if that one's already been destructed, things get bad.



    But here's a particular case where I just don't know whether behavior is well-defined: a static variable inside a function. Can I rely on the function behaving consistently even during program shutdown? Or is it possible that the static member will be destroyed, and the function will run anyway, without creating a new one?



    Here's a toy example demonstrating what I'm interested in:



    class Logger

    public:
    enum class Severity DEBUG, INFO, WARNING, ERROR ;
    void Log(Severity sev, const std::string& msg)

    LogImpl(FormatMessage(sev, msg));


    Logger() Log(Severity::INFO, "Logger active");
    ~Logger() Log(Severity::INFO, "Logger inactive");

    protected:
    static std::string FormatMessage(Severity sev, const std::string& msg)

    static const std::map<Severity, std::string> enum2str
    Severity::DEBUG, "DEBUG",
    Severity::INFO, "INFO",
    Severity::WARNING, "WARNING",
    Severity::ERROR, "ERROR"
    ;

    // Throws or crashes if enum2str is invalid, or uninitialized:
    return "[" + enum2str[sev] + "] " + msg;

    void LogImpl(const std::string& msg)

    std::cout << msg << std::endl;

    ;


    Let's imagine I have a global instance of Logger. The enum2str map in Logger::FormatMessage is a static variable, so at some point during program shutdown, it will be destroyed.



    By standard, can this cause my program to crash on shutdown? Is enum2str inherently unreliable during shutdown? Or is there some handling of this -- for example, if enum2str is invalid at some point, perhaps a new static instance will be created?



    (I am not interested in relying on destruction order between objects, e.g. where I declare the global Logger instance.)










    share|improve this question























      up vote
      6
      down vote

      favorite









      up vote
      6
      down vote

      favorite











      Quick context: I'm seeing errors on program shutdown, that stem from dependencies between global members (::sigh::, I know, I know). One global variable's destructor might refer to another global -- and if that one's already been destructed, things get bad.



      But here's a particular case where I just don't know whether behavior is well-defined: a static variable inside a function. Can I rely on the function behaving consistently even during program shutdown? Or is it possible that the static member will be destroyed, and the function will run anyway, without creating a new one?



      Here's a toy example demonstrating what I'm interested in:



      class Logger

      public:
      enum class Severity DEBUG, INFO, WARNING, ERROR ;
      void Log(Severity sev, const std::string& msg)

      LogImpl(FormatMessage(sev, msg));


      Logger() Log(Severity::INFO, "Logger active");
      ~Logger() Log(Severity::INFO, "Logger inactive");

      protected:
      static std::string FormatMessage(Severity sev, const std::string& msg)

      static const std::map<Severity, std::string> enum2str
      Severity::DEBUG, "DEBUG",
      Severity::INFO, "INFO",
      Severity::WARNING, "WARNING",
      Severity::ERROR, "ERROR"
      ;

      // Throws or crashes if enum2str is invalid, or uninitialized:
      return "[" + enum2str[sev] + "] " + msg;

      void LogImpl(const std::string& msg)

      std::cout << msg << std::endl;

      ;


      Let's imagine I have a global instance of Logger. The enum2str map in Logger::FormatMessage is a static variable, so at some point during program shutdown, it will be destroyed.



      By standard, can this cause my program to crash on shutdown? Is enum2str inherently unreliable during shutdown? Or is there some handling of this -- for example, if enum2str is invalid at some point, perhaps a new static instance will be created?



      (I am not interested in relying on destruction order between objects, e.g. where I declare the global Logger instance.)










      share|improve this question













      Quick context: I'm seeing errors on program shutdown, that stem from dependencies between global members (::sigh::, I know, I know). One global variable's destructor might refer to another global -- and if that one's already been destructed, things get bad.



      But here's a particular case where I just don't know whether behavior is well-defined: a static variable inside a function. Can I rely on the function behaving consistently even during program shutdown? Or is it possible that the static member will be destroyed, and the function will run anyway, without creating a new one?



      Here's a toy example demonstrating what I'm interested in:



      class Logger

      public:
      enum class Severity DEBUG, INFO, WARNING, ERROR ;
      void Log(Severity sev, const std::string& msg)

      LogImpl(FormatMessage(sev, msg));


      Logger() Log(Severity::INFO, "Logger active");
      ~Logger() Log(Severity::INFO, "Logger inactive");

      protected:
      static std::string FormatMessage(Severity sev, const std::string& msg)

      static const std::map<Severity, std::string> enum2str
      Severity::DEBUG, "DEBUG",
      Severity::INFO, "INFO",
      Severity::WARNING, "WARNING",
      Severity::ERROR, "ERROR"
      ;

      // Throws or crashes if enum2str is invalid, or uninitialized:
      return "[" + enum2str[sev] + "] " + msg;

      void LogImpl(const std::string& msg)

      std::cout << msg << std::endl;

      ;


      Let's imagine I have a global instance of Logger. The enum2str map in Logger::FormatMessage is a static variable, so at some point during program shutdown, it will be destroyed.



      By standard, can this cause my program to crash on shutdown? Is enum2str inherently unreliable during shutdown? Or is there some handling of this -- for example, if enum2str is invalid at some point, perhaps a new static instance will be created?



      (I am not interested in relying on destruction order between objects, e.g. where I declare the global Logger instance.)







      c++ static destructor






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 2 hours ago









      Ziv

      1,25011533




      1,25011533






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          2
          down vote













          Without seeing more of your program, the general answer is yes. That destruction of that static map can cause your program to have undefined behavior:




          [basic.start.term]



          3 If the completion of the constructor or dynamic initialization of an
          object with static storage duration strongly happens before that of
          another, the completion of the destructor of the second is sequenced
          before the initiation of the destructor of the first [...]



          4 If a function contains a block-scope object of static or thread
          storage duration that has been destroyed and the function is called
          during the destruction of an object with static or thread storage
          duration, the program has undefined behavior if the flow of control
          passes through the definition of the previously destroyed block-scope
          object. Likewise, the behavior is undefined if the block-scope object
          is used indirectly (i.e., through a pointer) after its destruction.




          In general, static objects are destroyed in reverse order to being initialized. So hypothetically, if you have a static object that is initialized early, before the map in the logger, and it logs something in its own destructor, you'll get undefined behavior.






          share|improve this answer



























            up vote
            2
            down vote














            I am not interested in relying on destruction order between objects




            You should, since that is exactly what determines whether FormatMessage is safe to call during the program shutdown.



            The code that runs during shutdown is destructors of static objects, and function registered with atExit.




            Can I rely on a function-scoped static variable for a method called during program shutdown?




            You cannot rely on it in general, but you can rely on it in certain circumstances.



            It is safe to rely on static objects in atExit, so it is safe to call FormatMessage there. Unless you can guarantee the order of destruction between particular static object s, and enum2str, it is not safe to use FormatMessage in the destructor of s.



            Static objects are guaranteed to be destroyed in reverse order of their construction. Therefore you can rely on enum2str existing during destruction of the subset of static objects whose constructors call FormatMessage, because calling FormatMessage in the constructor ensures that enum2str will have been constructed before that dependent static object has finished constructing.



            There is a trick to relying on a static object regardless of the order of destruction: Never destruct the dependee. This can be achieved by using a static pointer to a dynamically allocated object, that you intentionally never delete. As a drawback, this will trigger diagnostics in memory analyzers and may increase the blood pressure of your dogmatic co-workers.






            share|improve this answer






















              Your Answer





              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "1"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: false,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













               

              draft saved


              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52925392%2fcan-i-rely-on-a-function-scoped-static-variable-for-a-method-called-during-progr%23new-answer', 'question_page');

              );

              Post as a guest






























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              2
              down vote













              Without seeing more of your program, the general answer is yes. That destruction of that static map can cause your program to have undefined behavior:




              [basic.start.term]



              3 If the completion of the constructor or dynamic initialization of an
              object with static storage duration strongly happens before that of
              another, the completion of the destructor of the second is sequenced
              before the initiation of the destructor of the first [...]



              4 If a function contains a block-scope object of static or thread
              storage duration that has been destroyed and the function is called
              during the destruction of an object with static or thread storage
              duration, the program has undefined behavior if the flow of control
              passes through the definition of the previously destroyed block-scope
              object. Likewise, the behavior is undefined if the block-scope object
              is used indirectly (i.e., through a pointer) after its destruction.




              In general, static objects are destroyed in reverse order to being initialized. So hypothetically, if you have a static object that is initialized early, before the map in the logger, and it logs something in its own destructor, you'll get undefined behavior.






              share|improve this answer
























                up vote
                2
                down vote













                Without seeing more of your program, the general answer is yes. That destruction of that static map can cause your program to have undefined behavior:




                [basic.start.term]



                3 If the completion of the constructor or dynamic initialization of an
                object with static storage duration strongly happens before that of
                another, the completion of the destructor of the second is sequenced
                before the initiation of the destructor of the first [...]



                4 If a function contains a block-scope object of static or thread
                storage duration that has been destroyed and the function is called
                during the destruction of an object with static or thread storage
                duration, the program has undefined behavior if the flow of control
                passes through the definition of the previously destroyed block-scope
                object. Likewise, the behavior is undefined if the block-scope object
                is used indirectly (i.e., through a pointer) after its destruction.




                In general, static objects are destroyed in reverse order to being initialized. So hypothetically, if you have a static object that is initialized early, before the map in the logger, and it logs something in its own destructor, you'll get undefined behavior.






                share|improve this answer






















                  up vote
                  2
                  down vote










                  up vote
                  2
                  down vote









                  Without seeing more of your program, the general answer is yes. That destruction of that static map can cause your program to have undefined behavior:




                  [basic.start.term]



                  3 If the completion of the constructor or dynamic initialization of an
                  object with static storage duration strongly happens before that of
                  another, the completion of the destructor of the second is sequenced
                  before the initiation of the destructor of the first [...]



                  4 If a function contains a block-scope object of static or thread
                  storage duration that has been destroyed and the function is called
                  during the destruction of an object with static or thread storage
                  duration, the program has undefined behavior if the flow of control
                  passes through the definition of the previously destroyed block-scope
                  object. Likewise, the behavior is undefined if the block-scope object
                  is used indirectly (i.e., through a pointer) after its destruction.




                  In general, static objects are destroyed in reverse order to being initialized. So hypothetically, if you have a static object that is initialized early, before the map in the logger, and it logs something in its own destructor, you'll get undefined behavior.






                  share|improve this answer












                  Without seeing more of your program, the general answer is yes. That destruction of that static map can cause your program to have undefined behavior:




                  [basic.start.term]



                  3 If the completion of the constructor or dynamic initialization of an
                  object with static storage duration strongly happens before that of
                  another, the completion of the destructor of the second is sequenced
                  before the initiation of the destructor of the first [...]



                  4 If a function contains a block-scope object of static or thread
                  storage duration that has been destroyed and the function is called
                  during the destruction of an object with static or thread storage
                  duration, the program has undefined behavior if the flow of control
                  passes through the definition of the previously destroyed block-scope
                  object. Likewise, the behavior is undefined if the block-scope object
                  is used indirectly (i.e., through a pointer) after its destruction.




                  In general, static objects are destroyed in reverse order to being initialized. So hypothetically, if you have a static object that is initialized early, before the map in the logger, and it logs something in its own destructor, you'll get undefined behavior.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 1 hour ago









                  StoryTeller

                  86.1k12173240




                  86.1k12173240






















                      up vote
                      2
                      down vote














                      I am not interested in relying on destruction order between objects




                      You should, since that is exactly what determines whether FormatMessage is safe to call during the program shutdown.



                      The code that runs during shutdown is destructors of static objects, and function registered with atExit.




                      Can I rely on a function-scoped static variable for a method called during program shutdown?




                      You cannot rely on it in general, but you can rely on it in certain circumstances.



                      It is safe to rely on static objects in atExit, so it is safe to call FormatMessage there. Unless you can guarantee the order of destruction between particular static object s, and enum2str, it is not safe to use FormatMessage in the destructor of s.



                      Static objects are guaranteed to be destroyed in reverse order of their construction. Therefore you can rely on enum2str existing during destruction of the subset of static objects whose constructors call FormatMessage, because calling FormatMessage in the constructor ensures that enum2str will have been constructed before that dependent static object has finished constructing.



                      There is a trick to relying on a static object regardless of the order of destruction: Never destruct the dependee. This can be achieved by using a static pointer to a dynamically allocated object, that you intentionally never delete. As a drawback, this will trigger diagnostics in memory analyzers and may increase the blood pressure of your dogmatic co-workers.






                      share|improve this answer


























                        up vote
                        2
                        down vote














                        I am not interested in relying on destruction order between objects




                        You should, since that is exactly what determines whether FormatMessage is safe to call during the program shutdown.



                        The code that runs during shutdown is destructors of static objects, and function registered with atExit.




                        Can I rely on a function-scoped static variable for a method called during program shutdown?




                        You cannot rely on it in general, but you can rely on it in certain circumstances.



                        It is safe to rely on static objects in atExit, so it is safe to call FormatMessage there. Unless you can guarantee the order of destruction between particular static object s, and enum2str, it is not safe to use FormatMessage in the destructor of s.



                        Static objects are guaranteed to be destroyed in reverse order of their construction. Therefore you can rely on enum2str existing during destruction of the subset of static objects whose constructors call FormatMessage, because calling FormatMessage in the constructor ensures that enum2str will have been constructed before that dependent static object has finished constructing.



                        There is a trick to relying on a static object regardless of the order of destruction: Never destruct the dependee. This can be achieved by using a static pointer to a dynamically allocated object, that you intentionally never delete. As a drawback, this will trigger diagnostics in memory analyzers and may increase the blood pressure of your dogmatic co-workers.






                        share|improve this answer
























                          up vote
                          2
                          down vote










                          up vote
                          2
                          down vote










                          I am not interested in relying on destruction order between objects




                          You should, since that is exactly what determines whether FormatMessage is safe to call during the program shutdown.



                          The code that runs during shutdown is destructors of static objects, and function registered with atExit.




                          Can I rely on a function-scoped static variable for a method called during program shutdown?




                          You cannot rely on it in general, but you can rely on it in certain circumstances.



                          It is safe to rely on static objects in atExit, so it is safe to call FormatMessage there. Unless you can guarantee the order of destruction between particular static object s, and enum2str, it is not safe to use FormatMessage in the destructor of s.



                          Static objects are guaranteed to be destroyed in reverse order of their construction. Therefore you can rely on enum2str existing during destruction of the subset of static objects whose constructors call FormatMessage, because calling FormatMessage in the constructor ensures that enum2str will have been constructed before that dependent static object has finished constructing.



                          There is a trick to relying on a static object regardless of the order of destruction: Never destruct the dependee. This can be achieved by using a static pointer to a dynamically allocated object, that you intentionally never delete. As a drawback, this will trigger diagnostics in memory analyzers and may increase the blood pressure of your dogmatic co-workers.






                          share|improve this answer















                          I am not interested in relying on destruction order between objects




                          You should, since that is exactly what determines whether FormatMessage is safe to call during the program shutdown.



                          The code that runs during shutdown is destructors of static objects, and function registered with atExit.




                          Can I rely on a function-scoped static variable for a method called during program shutdown?




                          You cannot rely on it in general, but you can rely on it in certain circumstances.



                          It is safe to rely on static objects in atExit, so it is safe to call FormatMessage there. Unless you can guarantee the order of destruction between particular static object s, and enum2str, it is not safe to use FormatMessage in the destructor of s.



                          Static objects are guaranteed to be destroyed in reverse order of their construction. Therefore you can rely on enum2str existing during destruction of the subset of static objects whose constructors call FormatMessage, because calling FormatMessage in the constructor ensures that enum2str will have been constructed before that dependent static object has finished constructing.



                          There is a trick to relying on a static object regardless of the order of destruction: Never destruct the dependee. This can be achieved by using a static pointer to a dynamically allocated object, that you intentionally never delete. As a drawback, this will trigger diagnostics in memory analyzers and may increase the blood pressure of your dogmatic co-workers.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited 1 hour ago

























                          answered 1 hour ago









                          user2079303

                          72.2k552110




                          72.2k552110



























                               

                              draft saved


                              draft discarded















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52925392%2fcan-i-rely-on-a-function-scoped-static-variable-for-a-method-called-during-progr%23new-answer', 'question_page');

                              );

                              Post as a guest













































































                              Comments

                              Popular posts from this blog

                              List of Gilmore Girls characters

                              What does second last employer means? [closed]

                              One-line joke