2012-01-10 4 views
1

G ++ 버그를 발견했는데 확실하지 않습니다. 나는 그것을 설명 할 수 없다. 컴파일은 BAD 코드를 전달해서는 안되지만 잘못되었습니다. g ++ - 4.5 및 g ++ 4.6 -std = C++ 0x 경고없이이 코드를 전달합니다.G ++ 잘못된 STL 코드를 컴파일

마찬가지로 컴파일은 Bar 객체에 대한 포인터가 Bar 객체 자체라고 생각합니다. 나는 미쳤다. 나는 벌레를 얻기 위해 많은 시간을 보냈다. 이런 종류의 버그로부터 보호 할 수있는 기술이 있습니까?

나쁜 코드를 제공합니다

g++-4.6 for_stackoverflow.cpp && ./a.out 
address of bar in main() 0xbff18fc0 
Foo 0x9e80008  Bar  0xbff18fec 
Foo 0x9e80028  Bar  0xbff18fec 
Foo 0x9e80048  Bar  0xbff18fec 
end 

소스 코드 :

 #include <iostream> 
    #include <list> 
    #include <iomanip> 
    #include <algorithm> 

    #define BAD 

    using namespace std; 

    class Bar; 

    class Foo { 
    public: 
     virtual void tick(Bar & b) { 
     cout << "Foo " << this << "  Bar " << setw(14) << (&b) << endl; 
     }  
    }; 

    class Bar : public list<Foo*> { 
    }; 

    int main() { 
     Bar bar; 
     cout << "address of bar in main() " << &bar << endl; 
     bar.push_back(new Foo()); 
     bar.push_back(new Foo()); 
     bar.push_back(new Foo()); 
    #ifdef GOOD 
     for_each(bar.begin(), bar.end(), bind2nd(mem_fun(&Foo::tick), bar)); 
    #elif defined(BAD) 
     for_each(bar.begin(), bar.end(), bind2nd(mem_fun(&Foo::tick), &bar)); 
    #else 
    #error "define GOOD xor BAD" 
    #endif 
     cout << "end" << endl; 
     return 0; 
    } 

답변

0

bind2nd 선언과 같이

template <class Fn, class T> 
binder2nd<Fn> bind2nd(const Fn&, const T&); 

이 유형 T이 경우로, 추론되는 것을 의미 Bar *. 그 생각 컴파일 왜

template<typename _Operation, typename _Tp> 
inline binder2nd<_Operation> 
bind2nd(const _Operation& __fn, const _Tp& __x) 
{ 
    typedef typename _Operation::second_argument_type _Arg2_type; 
    return binder2nd<_Operation>(__fn, _Arg2_type(__x)); 
} 

를 보려면 : 내 시스템에서

가로 구현 것

진짜 문제가 될 것으로 보인다와, ++ g 컴파일 it's basically a reinterpret_cast 때문에 않습니다
class Bar {}; 

int main() { 
    Bar *b = 0; 
    typedef const Bar& type; 
    const type t = type(b); 
} 

.

간단한 해결 방법은 (C++ 11 또는 std::bind) boost::bind를 사용하도록 변경된다

#include <boost/bind.hpp> 

...

boost::bind(mem_fun(&Foo::tick), _1, &bar) 

또는 람다 함수 오류를 주는가를 당신은 볼 것을 기대합니다.

+0

bind2nd의 인수 유형이 실제 인수의 유형에서 추론 된 다음 점검 및 관리없이 급격히 변환됩니다. 이것은 다음과 같은 진정한 함정입니다 : (. char x; float f; f = * ((float *) (void *)) &x); –

+0

@ DaneelS.Yaitskov - 표준에서' 'static_cast (x)'대신''std :: bind1st'' /'std :: bind2nd'가 사용되지 않을 가능성이있는 이유 중 하나 인 것 같습니다. 'in C++ 11 – Flexo

관련 문제