2012-08-27 13 views
8

Ricevo strane limiti di comportamento controllo uno std :: membro array con MinGW (GCC 4.7.0) con il seguente codiceProblema con il controllo dei limiti un membro di std :: gamma all'interno di una funzione const

#include <iostream> 
#include <array> 

class testClass 
{ 
    std::array<int, 2> testArray; 

    public: 
     testClass(); 
     void func() const; 

}; 

testClass::testClass() : testArray({{1, 2}}) 
{ 
} 

void testClass::func() const 
{ 
    for (int i = 0; i < 2; ++i) 
     std::cout << testArray.at(i) << '\n' << testArray[i] << '\n';  
} 


int main() 
{ 
    testClass test; 
    test.func(); 
} 

L'uscita è

0 
1 
0 
2 

L'errore sembra essere correlato alla ottimizzazione, in quanto colture solo quando compilato con -O, ho provato le singole bandiere abilitate da -O ma non riusciva a restringere il campo oltre. Rendere la funzione non-const risolve anche il problema. Potrebbe essere un bug o mi manchi qualcosa?

* Modifica

ristretto la scelta, sembra un bug nella versione const di .at()

#include <iostream> 
#include <array> 

int main() 
{ 
    std::array<int, 2> const testArray = {1, 2}; 

    for (int i = 0; i < 2; ++i) 
     std::cout << testArray.at(i) << '\n' << testArray[i] << '\n';  
} 

stessa uscita come sopra compilato con -std=c++11 -O usando MinGW 4.7.0 su Windows XP SP3 e Windows 7 sp1.

* modifica 2

stessa uscita nuovamente

#include <iostream> 
#include <array> 

int main() 
{ 
    typedef std::array<int, 2> Tarray; 
    Tarray test = {1, 2}; 

    for (int i = 0; i < 2; ++i) 
     std::cout << const_cast<Tarray const*>(&test)->at(i) << '\n' << test.at(i) << '\n';  
} 
+0

http://liveworkspace.org/code/b0d5b3c7398f7e1a2e36838f23fc943c funziona bene. – ForEveR

+4

Sembra decisamente un bug per me. –

+0

Produce per me [un'uscita diversa] (http://ideone.com/ZhIsS) ... – dasblinkenlight

risposta

5

Questo fa parte della matrice intestazione

#ifdef __EXCEPTIONS 
    constexpr const_reference 
    at(size_type __n) const 
    { 
return __n < _Nm ? 
     _M_instance[__n] : throw out_of_range(__N("array::at")); 
    } 
#else 
    const_reference 
    at(size_type __n) const 
    { 
if (__n >= _Nm) 
    std::__throw_out_of_range(__N("array::at")); 
return _M_instance[__n]; 
    } 
#endif 

Undef __EXCEPTIONS nel file principale (o cambiate #ifdef per #ifndef in array) porta a uscita corretta Non lo so, questa è la soluzione giusta o no, ma funziona.

UPD: modificare il codice nell'intestazione del mio array per

#ifdef __EXCEPTIONS 
    constexpr const_reference 
    at(size_type __n) const 
    { 
return __n < _Nm ? 
     _M_instance[__n] : (throw out_of_range(__N("array::at"))), 
          _M_instance[__n]; 
    /*return __n < _Nm ? 
      _M_instance[__n] : throw out_of_range(__N("array::at"));*/ 
    } 
#else 
    const_reference 
    at(size_type __n) const 
    { 
if (__n >= _Nm) 
    std::__throw_out_of_range(__N("array::at")); 
return _M_instance[__n]; 
    } 
#endif 

Ora tutto funziona correttamente

+8

Il bug nell'intestazione non patchato è '__n <_Nm? _M_instance [__ n]: throw_of_range (__ N ("array :: at")) 'valuta un valore provvisorio (poiché un operatore condizionale deve valutare un valore di prvalue se uno degli operandi è un'espressione' throw' - C++ 11 5.16/2). La durata di questo temporaneo è solo fino alla fine dell'espressione completa dell'istruzione 'return' (C++ 11 12.2/5). Quindi la funzione 'at()' restituisce un riferimento const a qualcosa che non è più valido - il risultato è un comportamento non definito. –

+0

un bug orribile ('return a? B: throw c;') --- non avrebbe pensato che questo tipo di errore dei principianti arrivasse con qualsiasi container C++ spedito. – Walter

+3

@ Michael Burr: Penso che valga la pena di dare una risposta! –

Problemi correlati