2012-05-21 2 views
11

그래서 방금 대형 서버 응용 프로그램의 여러 시간 디버그 세션을 완료했습니다. 오류는 결국 생성자에서 거의 눈에 띄지 않는 오타가되었습니다. 기본적으로 다음과 같이 나타납니다.내 이니셜 라이저 목록에 작은 오자가있어 말할 수없는 고통을 초래합니다.

template <class T> 
class request_handler 
{ 
    public: 

    request_handler(T& request, Log& error_log) 
     : m_request(m_request), m_error_log(error_log) 
    { 
     /*... some code ... */ 
    } 

    ... 
}; 

버그를 확인 하시겠습니까? 글쎄, 나는하지 않았다. 문제는 이니셜 라이저 목록의 작은 오타입니다 : m_request(m_request)은 자체에 초기화되지 않은 참조를 할당하고 있습니다. 분명히 m_request(request)을 읽어야합니다.

이제 구성원 변수 m_requestT&입니다. 그래서 - 여기 컴파일러가 초기화되지 않은 변수를 사용하고 있다고 경고하지 않은 이유가 있습니까? -Wall 플래그 GCC 4.6을 사용

, 내가 말한다면 :

int x; 
x = x; 

이 ... 그것은 경고를 발행합니다 : 컴파일러하지 않은 이유, 그래서 warning: ‘x’ is used uninitialized in this function [-Wuninitialized]

을 나는 할당 할 때 저를 경고 본질적으로 자체에 초기화되지 않은 참조를 할당하는 것 : m_request? 그것은 나에게 성가심을 구해줬을 것이다.

+0

전체 최적화 (-O3)를 사용하여 컴파일 했습니까? 컴파일러는 실제로 데이터 흐름 분석을 수행 할 때 이러한 실수 중 일부만 인식합니다. m_ 접두사를 삭제하는 것도 고려하십시오. 'foo (T bar) : bar (bar)'는 완벽하게 잘 정의되어 있습니다. – xDD

+0

처음에는 최적화로 컴파일하고있었습니다. 하지만 디버깅하는 동안, 나는'-g3' 플래그로 컴파일하고 있었기 때문에 디버거를 사용할 수있었습니다. 'g3' 플래그로도 경고를 내지 못했습니다. – Channel72

+0

나는'-g3'이 어쨌든이 경고를 일으키는 것을 기대하지 않을 것입니다. – xDD

답변

11

추적하기 위해 귀찮은 버그. 그것은 자동으로 실패 할 템플릿이 필요하지 않습니다. 이 트릭을 할 것입니다 :

class C { 
     int a, b; 
public: 
     C(int t, int z) : a(a), b(z) { }; 
}; 

연타가 -Wuninitialized와이에 경고합니다.

gcc 사람들에게 좋은 소식 : gnu의 bugzilla에 따르면, gcc 4.7.0 has fixed this.

업데이트 GCC 4.7.0에

(sbellef에 의해 확인)이 경고를 얻을 -Wself-init을 추가

tst.cc : 생성자 '에서 C : C (INT, INT) 'tst.cc:4:9 : 경고 :'C 것은 :: 자체로 초기화 '된다 -Wuninitialized]

내가 생성자로 회원에 같은 이름을 사용하는 트릭을 사용하려면
+0

궁금한 점은, 회원 문서에 언급 된 버그 문서가 보이지 않지만 수정 사항이 두 경우 모두 동일하다는 것입니다. –

+1

좋은 지적. 4.7.0을 가진 사람이라면 누구나 소용돌이 치고 싶습니까? –

+0

내 시스템'gcc 버전 4.7.0 20120505 (시험판) (GCC) '에있는 GCC가 오류를보고하지 않는 것 같습니다. clang은 올바르게보고합니다 : clang ++ -Wall -c tst.cc tst.cc:4:29 : 경고 : 여기에서 사용할 때 필드가 초기화되지 않음 [-Wuninitialized] C (int t, int z) : a (a), b (z) {}; ^ 경고가 발생했습니다. ' – sbellef

3

매개 변수 에스.

template <class T> 
request_handler(T& request, Log& error_log) 
: request(request), error_log(error_log) 
{ 
    /*... some code ... */ 
} 

이렇게하면 항상 오류를 방지 할 수 있습니다. 함수 본문과 마찬가지로주의해야합니다. request은 멤버가 아니라 인수를 나타냅니다. 이것은 물론 참조와 같은 단순한 유형에는 문제가되지 않지만 클래스에는 권장하지 않습니다.

+0

그것이'T const & request'이어야하는 이유입니다. - 당신은'this-> request'를 초기화하기위한 인자 만 필요합니다. 당신은 그것을 수정하지 않을 것입니다. 유스 케이스가 더 복잡한 경우이 문제에 대해 권장합니다. 그러나 단순한 경우에이 패턴을 일관되게 사용한다면 추가 이점은 패턴을 인식 할 수있게된다는 것입니다. "오, 그 매개 변수'Foo'는 단지'Foo'를 초기화하기위한 것입니다.''Bar'를 조사하고 있으므로''Foo''에 대해 신경 쓸 필요가 없습니다." – MSalters