2011-02-07 8 views
1

저는 도서관을 쓰고 있으며 "Macros are evil"이라는 오래된 격언을 기억하면서 가능한 한 C++ 중심으로되고 싶었습니다. 소스 파일에서 C++ 문자열 상수 및 정적 변수 초기화

, 나는 다음과 같은 정의를했다 :

const std::string DATA_DIR_ENV_STR = "DATADIR" 
const std::string DFLT_DATA_DIR = "../data" 

/* 
#define DATA_DIR_ENV_STR "DATADIR" 
#define DFLT_DATA_DIR "../data" 
*/ 


std::string getRootDirectory() 
{ 
    char * datastr_ = getenv(DATA_DIR_ENV_STR); 

    if (datastr_) 
     return std::string(datastr_); 
    return DFLT_DATA_DIR; 
} 

// 헤더 파일 나는 다음과 같이 초기화 싱글 톤 클래스했다

std::string getRootDirectory(); 

:

bool mySingleton::inited = mySingleton::initialize(); 

bool mySingleton::initialize(){ 
    std::string rootdir = getRootDirectory(); // <-SEGV when using const std::string 
} 

라이브러리가 잘 컴파일되었지만 애플리케이션을 링크하면 앱이 항상 SEGV되었습니다. gdb를 사용하여 문제를 추적하고 충격/공포에 대해 문자열 변수 DATA_DIR_ENV_STR 및 DFLT_DATA_DIR은 정적 변수 초기화 중에 액세스되었을 때 아직 초기화되지 않았습니다.

결국 매크로를 사용하여 문제를 해결했습니다. 하지만 궁금한 점은 'static variable initialization fiasco'의 변형입니까? 매크로를 사용하지 않고도이를 해결할 수있는 또 다른 방법이 있습니까?

+1

, 당신은 당신이 돈을받을 :

귀하의 다른 옵션을 사용하여이를 반환하는 기능을 할 것이다. – Puppy

답변

2

예, 이것은 정적 초기화 실패가 당신을 뒤집어 놓는 것입니다.

는 "처음 사용할 때 구성"관용구 (뇌 - 컴파일 된 코드)입니다 피하는 방법 :

// In the header 
class mySingleton { 
    private: 
     static mySingleton *s_instance; 
     mySingleton(); 
    public: 
     mySingleton &instance() { 
      if (!s_instance) 
       s_instance = new mySingleton(); 
      return *s_instance; 
     } 
}; 

// And in the source file... 
mySingleton *mySingleton::s_instance; 

그러나, 문자열 상수의 경우, 당신은 또한 멀리 간단한 char 포인터 얻을 수 있습니다 :

static char const *const DATA_DIR_ENV_STR = "DATADIR"; 
static char const *const DFLT_DATA_DIR = "../data"; 
2

사실 그것은 분명히 나타납니다. 자세한 내용은 및 솔루션에 대한 내용은 http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14을 참조하십시오.

편집 : 문제를 자동으로 해결하는 단일 항목이 필요 없도록 다시 디자인 할 수 있습니다.

3

당신이 생각하기에 정적 초기화 문제입니다.

getenv 절에서 .c_str()을 사용한다고 가정합니다.

통계에 std :: string 대신 const char * const를 사용할 수 있습니다.

namespace { 
/*static*/ const char * const DATA_DIR_ENV_STR = "DATADIR"; 
/*static*/ const char * const DFLT_DATA_DIR = "../data"; 
} 

일반적으로 이제 익명 네임 스페이스를 사용하는 것이 정적 인 경우가 일반적입니다. 당신이 싱글 톤을 사용하는 경우

namespace { 
const std::string & DATA_DIR_ENV_STR() 
{ 
    static std::string s("DATADIR"); 
    return s; 
} 

const std::string& DFLT_DATA_DIR() 
{ 
    static std::string s("../data"); 
    return s; 
} 
}