C++ static const variable and destruction

ε祈祈猫儿з 提交于 2019-12-24 06:29:06

问题


I have encountered a strange behavior with a simple C++ class.

classA.h

class A
{
public:
  A();
  ~A();
  static const std::string CONST_STR;
};

classA.cpp

#include "classA.h"
#include <cassert>

const std::string A::CONST_STR("some text");

A::A()
{
  assert(!CONST_STR.empty()); //OK
}

A::~A()
{
  assert(!CONST_STR.empty()); //fails
}

main.cpp

#include <memory>  
#include <classA.h>  

std::auto_ptr<A> g_aStuff; 

int main() 
{ 
  //do something ... 
  g_aStuff = std::auto_ptr<A>(new A()); 
  //do something ... 
  return 0; 
}

I'd expect access violations or anything similar, but I'd never expect that the content of the static const string could change. Does anyone here have a good explanation what happens in that code?

thanks, Norbert


回答1:


I'd expect access violations or anything similar, but I'd never expect that the content of the static const string could change.

Undefined behaviour: it is undefined. If CONST_STR has been destroyed, then you are not guaranteed a hardware exception if you access it. It might crash, but then again its address might end up containing data which looks like an empty string: its destructor might clear pointers or whatever.

In this case, you say that the A instance is also stored in a global smart pointer, which is assigned in main(). So the CONST_STR has been constructed when it is accessed in the A constructor, but quite possibly is destroyed before the smart pointer is destroyed. We'd need the whole program to say for sure.

[Edit: you've done that. Since CONST_STR and g_aStuff are defined in different compilation units, their relative order of construction is not defined by the standard. I'm guessing that CONST_STR is being destroyed first.]




回答2:


Edit: Apparently the missing A:: was a typo in the original post of the code.

Original Answer:

Do you mean to have


    const std::string A::CONST_STR("some text");

so that the CONST_STR is part of class A?

Otherwise you are declaring it separately and not initializing the static member of A.




回答3:


You're creating 2 static variables in two different compilation units. There is no way to tell in which order they are initialized. But their destructors are always called in reverse order.

In your case it seems that next scenario took place:

g_aStuff constructor 
CONST_STR constructor

main funciton initializes g_aStuff

CONST_str destructor 
g_aStuff descrutor  

At this point result of CONST_STR.empty() is undefined. Which may trigger assert.




回答4:


The

const std::string CONST_STR("some text");
defined in classA.cpp is not a member of A. That definition would look like:
const std::string A::CONST_STR("some text");



回答5:


The standard doesn't specify the order of initialization of global/static objects in different translation units. It does, however, guarantee that each such object will be initialized before any function from that translation unit is executed.

In your case, it happens that CONST_STR is initialized after g_aStuff and, since the order of destruction is reverse from the order of construction, it gets destroyed before it. Thus, accessing CONST_STR from A's destructor invokes undefined behavior - you might get an access violation or you might not.

CONST_STR is, however, initialized before A's constructor is executed because they are in the same translation unit.




回答6:


It might happen if there is a global instance of A (or a static class member of type A). Since the order of the initialization of globals and statics is not defined (cross translation units), it can be.




回答7:


Looking at your full code, you're relying on the order of destruction across compilation units (classA.cpp and main.cpp). If you create g_aStuff as a local in main, your asserts should pass.



来源:https://stackoverflow.com/questions/1017755/c-static-const-variable-and-destruction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!