문제

간단한 C ++ 클래스로 이상한 행동을 만났습니다.

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; 
}

액세스 위반이나 비슷한 것을 기대하지만 정적 Const 문자열의 내용이 변경 될 수있을 것으로 기대하지 않습니다. 여기에 누구든지 그 코드에서 어떤 일이 일어나는지 좋은 설명이 있습니까?

고마워, 노버트

도움이 되었습니까?

해결책

액세스 위반이나 비슷한 것을 기대하지만 정적 Const 문자열의 내용이 변경 될 수있을 것으로 기대하지 않습니다.

정의되지 않은 행동 : 정의되지 않았습니다. const_str가 파괴 된 경우 액세스하면 하드웨어 예외가 보장되지 않습니다. 충돌이 발생할 수 있지만 다시 주소는 빈 문자열처럼 보이는 데이터가 포함될 수 있습니다. 소멸자는 포인터 나 그 밖의 다른 것을 제거 할 수 있습니다.

이 경우 A 인스턴스가 Main ()에 할당 된 글로벌 스마트 포인터에도 저장되어 있다고 말합니다. 따라서 Const_str는 A 생성자에 액세스 할 때 구성되었지만 스마트 포인터가 파괴되기 전에 상당히 파괴 될 수 있습니다. 우리는 확실히 말할 수있는 전체 프로그램이 필요합니다.

편집 : 당신은 그렇게했습니다. const_str 및 g_astuff는 다른 컴파일 단위로 정의되므로 상대적인 구성 순서는 표준에 의해 정의되지 않습니다. Const_str가 먼저 파괴되고 있다고 생각합니다.

다른 팁

편집하다: 분명히 누락 된 A:: 코드의 원래 게시물에서 오타였습니다.

원래 답변 :

당신은 가지고 있다는 것을 의미합니까?


    const std::string ㅏ::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 ()의 결과는 정의되지 않았습니다. 주장을 유발할 수 있습니다.

그만큼

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)의 파괴 순서에 의존합니다. Main의 로컬로서 g_astuff를 만들면 ASSERS가 통과해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top