C ++ статическая постоянная переменная и уничтожение

StackOverflow https://stackoverflow.com/questions/1017755

  •  06-07-2019
  •  | 
  •  

Вопрос

Я столкнулся со странным поведением простого класса C ++.

Класс a.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; 
}

Я бы ожидал нарушений доступа или чего-то подобного, но я бы никогда не ожидал, что содержимое статической строки const может измениться.У кого-нибудь здесь есть хорошее объяснение, что происходит в этом коде?

спасибо, Норберт

Это было полезно?

Решение

Я бы ожидал нарушений доступа или чего-нибудь подобного, но я бы никогда не ожидал что содержимое static const строка может измениться.

Неопределенное поведение:это не определено.Если CONST_STR был уничтожен, то вам не гарантируется аппаратное исключение при обращении к нему.Это может привести к сбою, но опять же, его адрес может в конечном итоге содержать данные, которые выглядят как пустая строка:его деструктор может очищать указатели или что-то в этом роде.

В этом случае вы говорите, что экземпляр A также хранится в глобальном интеллектуальном указателе, который присваивается в main().Таким образом, CONST_STR был создан при обращении к нему в конструкторе A, но, вполне возможно, уничтожен до уничтожения интеллектуального указателя.Нам нужна была бы вся программа, чтобы сказать наверняка.

[Править:ты сделал это.Поскольку CONST_STR и g_aStuff определены в разных единицах компиляции, их относительный порядок построения стандартом не определен.Я предполагаю, что CONST_STR уничтожается первым.]

Другие советы

Редактировать: По - видимому , пропавший A:: была опечатка в исходном сообщении кода.

Оригинальный Ответ:

Вы имеете в виду иметь


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

так что CONST_STR является частью класса A?

В противном случае вы объявляете его отдельно и не инициализация статического члена A.

Вы создаете 2 статические переменные в двух разных единицах компиляции.Нет никакого способа определить, в каком порядке они инициализируются.Но их деструкторы всегда вызываются в обратном порядке.

В вашем случае, похоже, имел место следующий сценарий:

g_aStuff constructor 
CONST_STR constructor

main funciton initializes g_aStuff

CONST_str destructor 
g_aStuff descrutor  

На данный момент результат CONST_STR.empty() не определен.Что может вызвать assert .

В

const std::string CONST_STR("some text");
определено в classA.cpp не является членом A.Это определение выглядело бы следующим образом:

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

Стандарт не определяет порядок инициализации глобальных / статических объектов в разных единицах перевода.Однако это гарантирует, что каждый такой объект будет инициализирован до выполнения какой-либо функции из этой единицы преобразования.

В вашем случае случается так, что CONST_STR инициализируется после g_aStuff и, поскольку порядок разрушения обратный порядку построения, он уничтожается раньше.Таким образом, доступ к CONST_STR От Aдеструктор вызывает неопределенное поведение - вы можете получить нарушение доступа, а можете и нет.

CONST_STR однако инициализируется перед Aконструктор выполняется, потому что они находятся в одной и той же единице перевода.

Это может произойти, если существует глобальный экземпляр A (или статический член класса типа A).Поскольку порядок инициализации глобальных значений и статики не определен (единицы перекрестного перевода), это может быть.

Глядя на ваш полный код, вы полагаетесь на порядок уничтожения в единицах компиляции (classA.cpp и main.cpp).Если вы создадите g_aStuff как локальный в main, ваши утверждения должны пройти.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top