2016-11-17 2 views
5

Ich habe den folgenden Code in einer Anwendung, die ich geerbt haben, gebaut gegen Auftrieb 1.48.0 VS2012Ausnahme von System undicht trotz try-catch

bool ConvertToBoolean(const std::string& s) 
{ 
    try 
    { 
    return boost::lexical_cast<bool>(s); 
    } 
    catch (...) 
    { 
    if (boost::iequals("true", s.c_str())) 
    { 
     return true; 
    } 
    } 
    return false; 
} 

mit der Wenn Sie „True“ oder "pass False "lexical_cast wird bei dieser Methode eine bad_lexical_cast-Ausnahme auslösen, da sie" 0 "oder" 1 "erwartet und stattdessen den Zeichenfolgenvergleich auswertet.

Das scheint auf meiner Maschine gut zu funktionieren, sowohl innerhalb als auch außerhalb des Debuggers (nicht immer? :)), aber auf einem unserer Kunden Maschinen die Ausnahme irgendwie "Lecks" und führt zu der folgenden Nachricht beim Debuggen der Dump-Datei mit:

Unbehandelte Ausnahme bei 0x000007FEFD08A06D in application.exe_161117_152748.dmp: Microsoft C++ Ausnahme: boost :: exception_detail :: clone_impl> auf Speicherplatz 0x00000000002CD9B8.

Stapelüberwachung:

KERNELBASE.dll!RaiseException() Unknown 
    snowagent.exe!_CxxThrowException(void * pExceptionObject, const _s__ThrowInfo * pThrowInfo) Line 154 C++ 
    application.exe!boost::throw_exception<boost::bad_lexical_cast>(const boost::bad_lexical_cast & e) Line 61 C++ 
    application.exe!boost::detail::lexical_cast_do_cast<bool,std::basic_string<char,std::char_traits<char>,std::allocator<char> > >::lexical_cast_impl(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & arg) Line 1750 C++ 
    application.exe!ConvertToBoolean(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & s) Line 111 C++ 
    application.exe!CScanner::Exec() Line 326 C++ 

Was diese Art von Leckagen verursachen könnte? Es ist extrem selten, dass Sie den Compiler verantwortlich machen, aber da es eine similar issue gibt, die been fixed in VS2015 hat, bin ich versucht, genau das zu tun, aber warum passiert es dann nicht auf meinem Rechner? Könnte es sein, dass ich VS2015 parallel zu VS2012 installiert habe und daher eine aktualisierte Laufzeit habe?

Zuletzt, wo in der folgenden Disassembly ist die Ausnahme Behandlung? Ich bin kein Experte für ASM, aber ich habe erwartet, dass es ein bisschen mehr ASM für diese Funktion ist. Ich kann nicht einmal den Anruf an boost::iequals sehen Update: Die Ausnahmebehandlung ist vorhanden, es befindet sich nur nicht in demselben Assemblyblock. Das Problem mit dem verknüpften Compiler scheint also nicht mit meinem Problem zusammenzuhängen. Es ist wahrscheinlich etwas anderes, als @Hans Passant in seinem Kommentar darauf hinweist.

107: bool ConvertToBoolean(const std::string& s) 
    108: { 
000000013FE654F0 mov   qword ptr [rsp+8],rcx 
000000013FE654F5 sub   rsp,38h 
000000013FE654F9 mov   qword ptr [rsp+20h],0FFFFFFFFFFFFFFFEh 
    109: try 
    110: { 
    111:  return boost::lexical_cast<bool>(s); 
000000013FE65502 call  boost::detail::lexical_cast_do_cast<bool,std::basic_string<char,std::char_traits<char>,std::allocator<char> > >::lexical_cast_impl (013FD1A0D3h) 
000000013FE65507 jmp   ConvertToBoolean+1Fh (013FE6550Fh) 
    112: } 
    113: catch (...) 
    114: { 
    115:  if (boost::iequals("true", s.c_str())) 
    116:  { 
    117:  return true; 
000000013FE65509 mov   al,1 
000000013FE6550B jmp   ConvertToBoolean+1Fh (013FE6550Fh) 
    118:  } 
    119: } 
    120: return false; 
000000013FE6550D xor   al,al 
    121: } 
000000013FE6550F add   rsp,38h 
000000013FE65513 ret 

Update: Für Vollständigkeit, ist dies die Ausnahme Block

114: { 
    115:  if (boost::iequals("true", s.c_str())) 
00007FF744D9F19B mov   rcx,qword ptr [s] 
00007FF744D9F19F call  std::basic_string<char,std::char_traits<char>,std::allocator<char> >::c_str (07FF74425E8B3h) 
00007FF744D9F1A4 mov   qword ptr [rbp+30h],rax 
00007FF744D9F1A8 lea   rcx,[rbp+28h] 
00007FF744D9F1AC call  std::locale::locale (07FF744252991h) 
00007FF744D9F1B1 mov   qword ptr [rbp+48h],rax 
00007FF744D9F1B5 mov   rax,qword ptr [rbp+48h] 
00007FF744D9F1B9 mov   qword ptr [rbp+50h],rax 
00007FF744D9F1BD mov   r8,qword ptr [rbp+50h] 
00007FF744D9F1C1 lea   rdx,[rbp+30h] 
00007FF744D9F1C5 lea   rcx,[CNTServiceCommandLineInfo::`vftable'+11170h (07FF744FBF778h)] 
00007FF744D9F1CC call  boost::algorithm::iequals<char const [5],char const * __ptr64> (07FF744251596h) 
00007FF744D9F1D1 mov   byte ptr [rbp+20h],al 
00007FF744D9F1D4 lea   rcx,[rbp+28h] 
00007FF744D9F1D8 call  std::locale::~locale (07FF74425D1C0h) 
00007FF744D9F1DD movzx  eax,byte ptr [rbp+20h] 
00007FF744D9F1E1 test  eax,eax 
00007FF744D9F1E3 je   [email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z$0+57h (07FF744D9F1F2h) 
    116:  { 
    117:  return true; 
00007FF744D9F1E5 mov   byte ptr [rbp+38h],1 
00007FF744D9F1E9 lea   rax,[ConvertToBoolean+37h (07FF7444C8FD7h)] 
00007FF744D9F1F0 jmp   [email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z$0+5Eh (07FF744D9F1F9h) 
    118:  } 
    119: } 
00007FF744D9F1F2 lea   rax,[ConvertToBoolean+35h (07FF7444C8FD5h)] 
00007FF744D9F1F9 add   rsp,28h 
00007FF744D9F1FD pop   rdi 
00007FF744D9F1FE pop   rbp 
00007FF744D9F1FF ret 
+0

Wenn diese Ausnahme ausgelöst wird, während sich der Stapel von einer anderen Ausnahme löst, wird Ihr 'catch' nicht getroffen. In diesem Fall sollte in Ihrem Stack ein Aufruf von 'std :: terminate' erfolgen. –

+0

Wenn es nur so einfach wäre, Gut gedacht. – Per

+0

Den Compiler zu beschuldigen kann eine bequeme Erklärung sein, aber diese Benutzer führen ihren eigenen Compiler nicht aus. Sehen Sie sich also genauer an, was Sie wissen. Beachten Sie das "at memory location ..." Detail. Nur wenige Ausnahmen melden einen Speicherort. Sicher nicht schlecht_lexical_cast. Ziemlich wahrscheinlich, dass dieses Leben als Ausnahme für Zugriffsverletzungen begann und Sie Code haben, der es in eine C++ - Ausnahme übersetzt, wie '_set_se_translator()'. Mit anderen Worten, es war "Wurf", der fehlgeschlagen ist. AVE wird normalerweise durch Speicherbeschädigung verursacht. Wenn man Glück hat, kann man sie auf eine Maschine lokalisieren –

Antwort

0

Nach langer Suche im Code ich einen Puffer von nicht weniger als 80 Bytes überrannt gefunden.

STARTUPINFO startup_info; 
PROCESS_INFORMATION process_information; 
ZeroMemory(&startup_info, sizeof(startup_info)); 
ZeroMemory(&process_information, sizeof(startup_info)); <-- wrong size! 

Dieser Code nie auf meiner Maschine während des Tests ausgeführt, warum also der Code in der ursprünglichen Frage in diesen Tests gut funktioniert. Ein überschriebener Stapel ist offensichtlich katastrophal und kann jede Menge seltsamer Verhaltensweisen verursachen.