Frage

Ich habe, was ich bin mir ziemlich sicher, dass ein Fehler in den Optimierer in Visual Studio 2005. Das Problem ist, mit einem STL Karte.

Hier ist der relevante Code:

MyMapIterator myIt = m_myMap.find(otherID);

if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_A)
{
    //Prints stuff.  No side-effects whatsoever.
}
else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_B && myIt->second.foo == FOO_A)
{
    //Prints stuff.  No side-effects whatsoever.
}
else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_B && myIt->second.foo == FOO_B && /*other meaningless conditions */)
{
    //Prints stuff.  No side-effects whatsoever.
}

funktioniert einwandfrei im Debug, verwendet in Version zum Absturz zu bringen, und deaktivieren globale Optimierungen „fixed it“ Nun, nichts funktioniert. Ich erhalte ein:

Microsoft Visual Studio C Runtime Library has detected a fatal error in [...]

Press Break to debug the program or Continue to terminate the program. 

Dies geschieht auf der Seite ersten MyMapIterator :: operator-> der letzten else if

Die Karte leer ist, weiß ich, dass zurück Ende haben finden soll () Die ersten beiden Vergleiche in diesem Sinne arbeiten. Aber irgendwie, das dritte Mal 'Myit! = M_myMap.end ()' gibt true zurück, und die rechte Seite des && ausgeführt wird.

Verschiedene andere Orte nicht wie diese mit einer Variante von ‚Myit! = M_myMap.end ()‘ in derselben Datei wahr Rückkehr, aber das ist für mich derjenige, der die meisten anderen Möglichkeiten ausgeschlossen ist. Früher dachte ich, es ist ein Pufferüberlauf war, die auf meiner Karte wurde stampfen, aber einen Blick zurück auf den Code nehmen. Ich bin sicher, dass kein anderer Thread auf es stampft, und das ist 100% reproduzierbar.

Also, was soll ich tun, von hier. Dies ist nicht die Leistung empfindlich im geringsten. Ich brauche es nur zu arbeiten, wie es sollte. Jede Option ist akzeptabel. Ja, ich weiß, ich könnte die ganze Sache mit der Iterator Gleichheitsprüfung umgeben und es ist nicht der schönste Code. Der Punkt ist, es sollte immer noch funktionieren, und wenn das nicht funktioniert, Sonstigem.

Bearbeiten

Die letzte else-if erzeugt keinen Sprung!

    if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_A)
009270BE  mov         ecx,dword ptr [this] 
009270C4  add         ecx,0Ch 
009270C7  lea         eax,[ebp-90h] 
009270CD  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::end (8A21E0h) 
009270D2  mov         esi,eax 
009270D4  lea         edi,[myIt] 
009270D7  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::const_iterator::operator!= (8A2220h) 
009270DC  movzx       ecx,al 
009270DF  test        ecx,ecx 
009270E1  je          lux::Bar::DoStuff+0E4h (927154h) 
009270E3  lea         esi,[myIt] 
009270E6  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::iterator::operator-> (8A21F0h) 
009270EB  cmp         dword ptr [eax+8],1 
009270EF  jne         lux::Bar::DoStuff+0E4h (927154h) 
    {
         Stuff
    }
    else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_B)
00927154  mov         ecx,dword ptr [this] 
0092715A  add         ecx,0Ch 
0092715D  lea         eax,[ebp-98h] 
00927163  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::end (8A21E0h) 
00927168  mov         esi,eax 
0092716A  lea         edi,[myIt] 
0092716D  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::const_iterator::operator!= (8A2220h) 
00927172  movzx       edx,al 
00927175  test        edx,edx 
00927177  je          lux::Bar::DoStuff+17Ah (9271EAh) 
00927179  lea         esi,[myIt] 
0092717C  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::iterator::operator-> (8A21F0h) 
00927181  cmp         dword ptr [eax+8],2 
00927185  jne         lux::Bar::DoStuff+17Ah (9271EAh) 
    {
            //Stuff
     }
    else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_C)
009271EA  mov         ecx,dword ptr [this] 
009271F0  add         ecx,0Ch 
009271F3  lea         eax,[ebp-0A0h] 
009271F9  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::end (8A21E0h) 
009271FE  mov         esi,eax 
00927200  lea         edi,[myIt] 
00927203  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::const_iterator::operator!= (8A2220h) 
00927208  lea         esi,[myIt] 
0092720B  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::iterator::operator-> (8A21F0h) 
    {
            //Stuff in the condition and after
War es hilfreich?

Lösung 2

Nun Jungs. Nach viel Schmerz und Tränen. Um es zu beheben zumindest zeitweise hatte ich den Code ein wenig auf die Form von den meisten Menschen vorgeschlagen zu überarbeiten, das ist, wie es im ersten Fall sein sollte:

if (myIt != m_myMap.end())
{
    if (myIt->second.userStatus == STATUS_A) 
    {
        //Prints stuff.  No side-effects whatsoever.
    }
    else if (myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_A)
    {        
        //Prints stuff.  No side-effects whatsoever.
    }
    else if (myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_B && /*other meaningless conditions */)
    {
        //Prints stuff.  No side-effects whatsoever.
    }
}

Allerdings war der Fehler immer noch vorhanden. Dieses Juwel es fest:

if (myIt != m_myMap.end())
if (myIt != m_myMap.end())
{
    if (myIt->second.userStatus == STATUS_A) 
    {
        //Prints stuff.  No side-effects whatsoever.
    }
    else if (myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_A)
    {        
        //Prints stuff.  No side-effects whatsoever.
    }
    else if (myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_B && /*other meaningless conditions */)
    {
        //Prints stuff.  No side-effects whatsoever.
    }
}

Ja. Verdoppeln des resultiert, wenn in einem Sprungbefehl nach dem Test emittiert wird.

Andere Tipps

Ich vermute, Sie Code an anderer Stelle haben, die einen Puffer über Lauf in sich hat.

Das andere Code ist die Verwaltung des Speichers zu zerstören, die der entsandte Code verwendet wird.

Im Debug-Modus der zusätzliche Speicher padding das Verhalten ändern.

anderen Zufallscode ändert, wird auch das Verhalten ändern, da es die relative Position der Dinge verschieben.

Im Grunde müssen Sie eine Menge Code oder verwenden Sie ein Tool wie Bounds überprüfen, die Fehler zu finden.

Konzentrieren Sie sich auf Arrays oder irgendwelche Rohzeiger Mathematik. Auch eine Verwendung von gelöschten Zeigern.

Bugs wie diese können für eine lange Zeit verstecken, wenn sie Ort schreiben, die nicht zu einem Absturz verursacht. Aus dem gleichen Grund verschwinden sie oft auf mysteriöse Weise.

Es scheint wahrscheinlich, dass Sie eine andere Bedingung im Code haben Sie das nicht gezeigt haben, ist die Karte verursacht bei einigen ungültigen Daten gefüllt werden.

Versuchen Sie den Inhalt der Karte, bevor Sie Ihren Anruf Dumping, um zu find(), und hat einen Blick für mögliche nicht initialisierte Werte in dem Rest des Codes.

offensichtlich kann alles Fehler, auch die VC-Compiler. so, wenn es einen Fehler in diesem Abschnitt des Codes ist, könnten Sie es wickeln in einem # Pragma drehen Optimierungen aus. Wenn es immer noch danach abstürzt, dann ist etwas anderes in Ihrem Code Ihre Karte Wegwerfen (und dann müssen Sie auf DrWatson drehen Dumps zu erhalten, so dass Sie den Absturz in windbg überprüfen können, um zu versuchen und herausfinden, was es passiert ist).

So deaktivieren Sie Optimierung Verwendung:

#pragma optimize("g", off)

, um ihn wieder auf, entweder ausgeschaltet oder auf den speziellen Fall verwenden ändern

#pragma optimize("", on)

, die Ihre Optimierungseinstellungen auf die Projektvorgaben zurücksetzt.

Der Optimierer vermasselt wirklich Ihre Debugging-Informationen auf. Es gibt eine sehr gute Chance, dass die Linie, die ist wirklich auf einer andere, in der Nähe Linie versagt. Auch wenn der Debugger sagt Ihnen, dass die Ausnahme auf der zweiten Hälfte des && Betreiber auftritt, ist es wahrscheinlich nicht.

das eigentliche Problem zu diagnostizieren, können Sie die Pause wollen die letzte if-Anweisung in etwas nach oben wie:

else if (myIt != m_myMap.end())
{
    printf("TEST 1\n");
    if (myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_B && /*other meaningless conditions */)
    {
        //Prints stuff.  No side-effects whatsoever.
    }
}

printf("TEST 2\n");

Wenn Sie eine Ausgabe von „TEST 1“ erhalten, dann gibt es etwas falsch mit Ihrem Iterator. Wenn Sie eine Ausgabe von „TEST 2“ und dann einem Absturz zu bekommen, dann ist offensichtlich der Fehler in dem nachfolgenden Code auftritt. Wenn weder "TEST 1" noch "TEST 2" druckt und stürzt immer noch da, dann ist etwas wirklich falsch.

Ich glaube, ich in diese genau das gleiche Problem lief.

scheint nur in x64 Release passieren (vollständige Optimierung). Meine STL Karte leer bestätigt (size () == 0), aber diese Zeile Code nicht erkennt, die leere Karte und stattdessen geht in die for-Schleife:

typedef std::map<std::string,std::string> KeyValueMap;

printf( "size: %d\n", ExtraHeaders.size() ); // prints "size: 0"

for( KeyValueMap::iterator it= ExtraHeaders.begin(); it != ExtraHeaders.end(); it++ )
{
    // this line is executed
    printf( "%s\t%s\n", (*it).first.c_str(), (*it).second.c_str() );
}

Man fühlt sich wie ein Compiler Fehler zu mir.

  

Ja, ich weiß, ich könnte die ganze Sache mit der Iterator Gleichheitsprüfung umgeben und es ist nicht der schönste Code. Der Punkt ist, es sollte immer noch funktionieren, und wenn das nicht funktioniert, etwas anderes kann.

Natürlich mit dieser Logik haben Sie keine Optionen ... Alles, was Sie tun, eine Abhilfe ist.

Ich glaube, mein erster Ansatz wäre, die Sachen in einem Block zu wickeln, die überprüft haben, dass myIt gilt:

if (myIt != m_myMap.end())
{
    if (myIt->second.userStatus == STATUS_A) 
    {
        //Prints stuff.  No side-effects whatsoever.
    }
    else if (myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_A)
    {        
        //Prints stuff.  No side-effects whatsoever.
    }
    else if (myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_B && /*other meaningless conditions */)
    {
        //Prints stuff.  No side-effects whatsoever.
    }
}

Ich denke, man eine Annahme stellen, für die wahrscheinlich falsch ist: dass der Absturz passiert, nachdem erfolgreich myIt != m_myMap.end() && myIt->second.userStatus in der gleichen Iteration geprüft. Ich würde wetten, dass der Absturz sofort das erste Mal, folgt diese Werte untersucht werden. Es ist das Optimierungsprogramm, das es habe die ersten beiden if Bedingungen gelöscht aussehen wie Sie macht.

Versuchen Sie, einen völlig anderen Code-Block in die Schleife setzen und sehen, ob es dort stürzt ab (meine Wette ist, dass es würde - ich glaube nicht, dass Sie die Ausgabe von cerr sehen werden sofort zu einem Absturz vorhergehenden.)

// New code block
MyMapIterator yourIt = m_myMap.find(otherID);
if (yourIt != m_myMap.end() && yourIt->second.userStatus == STATUS_A || 
     yourIt->second.userStatus == STATUS_B)
{
        cerr << "Hey, I can print something! " << std::ios::hex << this << endl;
}

// Original code
MyMapIterator myIt = m_myMap.find(otherID);
if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_A)
{
        //Prints stuff.  No side-effects whatsoever.
}
else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_A)
{
        //Prints stuff.  No side-effects whatsoever.
}
else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_B && /*other meaningless conditions */)
{
        //Prints stuff.  No side-effects whatsoever.
}
if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_B && myIt->second->foo == FOO_A)

Warum zugreifen Sie Userstatus mit. und foo mit ->

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top