2016-05-08 3 views
0

Bemerkt eine eigentümliche Verhalten aufgerufen, wenn std :: map aus einer Funktion, die nicht den Zustand seines Objekts ändern:Karte <string, int> wirft std :: out_of_range, wenn sie von konstanter Funktion

std::map<std::string, int> _attribLocations; 
... 
int ProgramInfo::getAttribLocation(const std::string& name) const 
{ 
    return _attribLocations.at(name); 
} 

Als ich das nennen Funktion, vorbei an einer Stringliteral, die Lookup wirft out_of_range Ausnahme:

auto index = info.getAttribLocation("v_position"); 

ich bemerkte, gibt es zwei Versionen an(), eine, die eine const_iterator verwendet, und eine, die nicht:

mapped_type& at(const key_type& _Keyval) 
     { // find element matching _Keyval 
     iterator _Where = _Mybase::lower_bound(_Keyval); 
     if (_Where == _Mybase::end() 
      || _Mybase::_Getcomp()(_Keyval, _Mybase::_Key(_Where._Mynode()))) 
      _Xout_of_range("invalid map<K, T> key"); 
     return (_Where->second); 
     } 

    const mapped_type& at(const key_type& _Keyval) const 
     { // find element matching _Keyval 
     const_iterator _Where = _Mybase::lower_bound(_Keyval); 
     if (_Where == _Mybase::end() 
      || _Mybase::_Getcomp()(_Keyval, _Mybase::_Key(_Where._Mynode()))) 
      _Xout_of_range("invalid map<K, T> key"); 
     return (_Where->second); 
     } 
    }; 

Es ist wie der Teil scheint, dass es zu werfen verursacht ist:

_Mybase::_Getcomp()(_Keyval, _Mybase::_Key(_Where._Mynode()))

ich nicht wirklich debuggen jede tiefer.

Ich bin mit Visual Studio 2015

Ich bin sicher, dass der Schlüssel in der Karte existiert übergeben wird (von der Karte mit einem Debugger Inspektion). Könnte es ein Fehler in der Map-Implementierung sein, oder fehlt mir etwas beim Vergleichen von Strings?

+1

Ich verwende VS2015 Update 2 und kann dieses Verhalten nicht reproduzieren. Haben Sie versucht, dies in einem minimalen Beispielprojekt zu reproduzieren? – Wurmloch

+5

Sie müssen uns [MCVE] (http://stackoverflow.com/help/mcve) zeigen. –

+0

Vergiss es, ich bin dumm. –

Antwort

1

Ah, dummer Fehler! Es stellte sich heraus, dass die in meiner Karte gespeicherten Schlüssel mit abschließenden Zeichen gefüllt waren (sie waren Tausende von Zeichen lang, meistens '\ 0'). Ich habe String-Literale wie "gl_position" übergeben und das Nachschlagen fand eigentlich gar nichts. Ich habe den Operator [] in der nicht-const-Funktion verwendet, die den Standardwert int (0) zurückgibt, den ich sowieso erwartet habe. aber bei() konnte den Wert nicht finden, und warf. Hier ist, was passiert war:

class A 
{ 
public: 

    A() 
    { 
     char* foo = (char*)malloc(40000); 
     foo[0] = 'f'; 
     foo[1] = 'o'; 
     foo[2] = 'o';  

     for (int i = 3; i < 40000; i++) 
      foo[i] = '\0'; 

     std::string fooStr(foo, 40000); 

     map[fooStr] = 5; 
    } 


    int getAttribLocation(const std::string name) 
    { 
     return map[name]; 
    } 

private: 
    std::map<std::string, int> map; 
}; 

int main() 
{ 
    A instance; 

    auto x = instance.getAttribLocation("foo"); 
    return 0; 
} 

Die Verwirrung kam aus Umschalten zwischen [] und(), weil ich nicht [] in einer konstanten Funktion nutzen zu können.

+0

Und Sie verstehen, dass Sie das beheben können, indem Sie einfach 'std :: string fooStr (foo);' richtig? Übergeben Sie also kein Längenargument an den Konstruktor. –

+0

Ah, ja, das ist besser als manuell schneiden. –

Verwandte Themen