2013-02-17 4 views
2

내 네임 스페이스에서 const 객체를 초기화하는 중 문제가 발생합니다. 내가 초기화를 디버깅 할 경우네임 스페이스에서 const 객체 복원

namespace myNamespace{ 
    const std::string HI = "Hi"; 
    const std::string BYE = "Bye"; 

    inline std::vector<std::string> createHiAndByeVector(){ 
     std::vector<std::string> temp; 
     temp.push_back(HI); 
     temp.push_back(BYE); 
     return temp; 
    } 

    const std::vector<std::string> HI_AND_BYE = createHiAndByeVector(); 
} 

, 나는 HIBYE 모두 문자열 리터럴을 할당받을 것을 볼 수있다 : 나는 다음과 같은 네임 스페이스를 가지고있다. 실행은 HI_AND_BYE의 initialziae로 계속되지만 createHiAndByeVector() 함수에 들어가면 HIBYE은 더 이상 값을 갖지 않습니다. 그런 다음 push_back() 메서드에서 세그먼트 오류가 발생합니다. 호출 스택을 보면 라인이 표시됩니다 : __static_initialization_and_destruction_0(). 무슨 일 이니? 내 물건이 건설 된 직후 파괴되고 있습니까?

+0

왜 이렇게 성 가시지 : 'std :: vector const HI_AND_BYE { "안녕", "안녕"};'라고 말할 수 있습니다. –

+1

이러한 모든 정의는 동일한 번역 단위 (.cpp 파일)에 나타 납니까? –

+0

'HI_AND_BYE'에 따라 다른 정적 멤버가 있습니까? 정적 초기화 문제의 종류 – billz

답변

-1

저는 이것이 초기화 휘황 (Fiisco) 때문이라고 생각합니다. 다음 링크는 도움이 될 수 있습니다. 문제는 Global/Static 변수가 무작위로 초기화된다는 것입니다. 그것들을 초기화하는 특별한 순서는 없습니다. 따라서 HI 또는 BYE가 초기화되기 전에 HI_AND_BYE가 초기화됩니다.

Finding C++ static initialization order problems

http://www.parashift.com/c++-faq-lite/static-init-order.html

+1

단일 번역 단위 내의 객체의 초기화 순서는 잘 정의되어 있으며 선언 순서대로되어 있습니다. 예 : parashift의 C++ FAQ는 "별도의 소스 파일에 존재하는"객체에 대해 언급합니다. –

+0

아아, 그것을 지적 해 주셔서 감사합니다 :) – Deamonpog

1

내 생각 엔 여기에 문제가 하나의 정의 규칙 (ODR)의 위반이라는 것이다. 여기서 추측하는 것은이 코드가 실제로 헤더에 있다는 것입니다. 이는 인라인으로 함수를 선언 한 이유이기도합니다.

이제이 코드는 여러 번역 단위 (.cpp 파일), TU1 및 TU2로 컴파일됩니다. 이것은 상수 함수와 인라인 함수의 두 세트로 연결됩니다. 이제 연결될 때 상수는 내부 연결 (네임 스페이스 수준의 const가 원인) 때문에 서로 독립적으로 존재합니다. 그러나 함수에는 내부 연결이 없으며 대신 링커는 inline을 통해 인스턴스를 제외한 모든 인스턴스를 삭제하도록 지시됩니다. 이제 나머지 하나는 TU1과 TU2에서 벡터를 초기화하는 데 사용되지만 그 중 하나의 상수 문자열을 사용합니다. 초기화되지 않은 경우 초기화되는 시점에 따라 작동하거나하지 않을 수 있습니다. 이것은 기본적으로 Deamonpog가 언급 한 초기화 순서 실패입니다.

ODR로 되돌아 가면 문제는 인라인 함수가 두 번 컴파일되지만 서로 다른 문자열 상수를 암시 적으로 참조하기 때문에 같지 않다는 점입니다. 머리말에 익명의 네임 스페이스가있을 때도 비슷한 문제가 발생합니다. BTW : 그 외에도이 문제는 네임 스페이스와 아무런 관련이 없습니다! 이 문제를 해결하는 방법은 두 가지가 있습니다.

  1. init 함수도 정적으로 만듭니다. 이것은 다른 모든 번역 단위에서이 모든 상수와 기능을 형제들과 분리합니다.
  2. 헤더의 상수를 (extern string const BYE;) 개 선언하고 별도의 TU에 구현하십시오 (string const BYE = "Bye!";). 그렇게하면 프로그램의 다른 부분에서 공유 할 수있는 단일 인스턴스 만 가질 수 있습니다.
+0

자세한 답변을 주셔서 감사합니다. 네임 스페이스 내의 함수는 암묵적으로, 이미 정적 인 두 개의 문자열'HI'와'BYE'와 같이 정적이라고 생각했습니다. 그러한 경우, 왜 문자열의 "사본"이 여러 개 있습니까? 헤더 만 라이브러리를 만들고 있으므로 옵션 2를 피하려고합니다. 실제로, 그것은 내가 재 작성하려고하는 시나리오입니다. – Wagan8r