2012-08-13 7 views
2

익명 네임 스페이스 안에 전역 변수가 있습니다. cpp 파일 내의 전역 변수

namespace { 
std::unordered_map<std::string, std::string> m; 
} 


A::A() { m.insert(make_pair("1", "2")); } // crasches 
void A::insert() { m.insert(make_pair("1", "2")); } // ok 

생성자 내부의 map를 사용하려고하면

나는 액세스 위반 읽기 위치를 얻는다. 그러나 A이 초기화 된 후에 사용하면 작동합니다.
이 문제가 해결 되었습니까?

+1

더 많은 코드가 필요합니다. –

+0

정적 멤버 'A'가 있습니까? –

+1

다른 cpp 파일에 정의 된 전역 A 인스턴스가있는 경우이 인스턴스와 m의 작성 순서는 정의되지 않습니다. –

답변

8

생성자 호출이 충돌을 일으키는 A 개체의 범위는 무엇입니까?

정적 초기화가 실행되는 순서에 관해서는 보장이 없습니다 그래서 당신 A 객체는 인 경우 (m이기 때문에),이 m이되는 측면에서 아직 존재하지 않는 것을 확실히 가능 전역 또는 정적 validly constructed 객체로, std::unordered_map::insert()에 대한 호출이 초기화되지 않은 메모리에서 호출되어 충돌로 이어질 수 있습니다.

해결 방법은 m에 의존하는 모든 A 인스턴스가 정적/전역 적으로 명시 적으로 구성되며 (사용자가 동일한 TU에있는 경우 주석 기가 추가로 올바르게 정렬되도록) 구성됩니다. 또는 삽입을 수행하기 위해 나중에 인스턴스에서 함수를 호출 할 수 있도록 A의 구조를 변경하십시오. 이것이 유효한 솔루션인지 여부는 A의 사용에 따라 다릅니다.

+0

하나의 수정 : ** 번역 단위 **에는 그러한 보증이 없습니다. 하나의 번역 단위 내에서 선언 순서대로 초기화됩니다. – atzz

+0

그리고 한 가지 추가 : 정적 개체 초기화 간의 종속성을 피하는 것이 가장 좋습니다. 그러나 그것을 할 수없는 경우 - 일반 정적 변수 대신에 액세스시 생성 싱글 톤을 사용하십시오. – atzz

+0

** 사용자가 설명이 정확하면 ** 문제가 될 가능성은 낮습니다 ** (그러나 우리는 조각이 누락 된 것으로 추측합니다). 그것은 익명의 네임 스페이스에 있기 때문에 이미 익명 네임 스페이스 개체가 그런 방식으로 제한되어 있으므로 동일한 번역 단위에 있습니다. 위에 표시된 코드는 A 앞에 선언 할 m을 보여줍니다 (상상할 수있는 것이 많지만). 따라서 초기화 순서가 문제가되어서는 안됩니다 (단순한 전역 순서 재 지정이 문제를 해결해야하는 경우). –

2

응용 프로그램의 어딘가에, 즉 main() 함수가 실행되기 전에 즉, m이 초기화되기 전의 정적 컨텍스트에서 A 유형의 클래스를 작성 중일 수 있습니다.