I have the following code in an application that I inherited, built against boost 1.48.0 using VS2012
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; }
If you pass this method True or False, lexical_cast will throw a bad_lexical_cast exception because it expects a "0" or "1" and compares the strings instead.
This seems to work fine on my machine, both inside and outside the debugger (not always? :)), but on one of our client machines the exception somehow βleaksβ and leads to the next message when debugging using a file dump:
Unhandled exception at 0x000007FEFD08A06D in application.exe_161117_152748.dmp: Microsoft C ++ exception: boost :: exception_detail :: clone_impl> in memory location 0x00000000002CD9B8.
Stack trace:
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++
What could cause such a leak? It is extremely rare that you blame a compliment, but since there is a similar problem that has been fixed in VS2015. I am tempted to do just that, but then why doesn't this happen on my machine? Maybe because I have VS2015 installed in parallel with VS2012 and, therefore, has an updated runtime?
Finally, where in the next breakdown is exception handling used? I am not an expert in ASM, but I expected this to be a bit more ASM for this feature. I donβt even see the boost::iequals Update call : exception handling is present, it just is not in one assembly block. Therefore, the problem of the linked compiler is not related to my problem. Probably something else, as @Hans Passant points out in his comment.
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: for completeness, this is an exception 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 __catch$?ConvertToBoolean@ @ YA_NAEBV?$basic_string@DU ?$char_traits@D @ std@ @ V?$allocator@D @ 2@ @ std@ @@Z$0+57h (07FF744D9F1F2h) 116: { 117: return true; 00007FF744D9F1E5 mov byte ptr [rbp+38h],1 00007FF744D9F1E9 lea rax,[ConvertToBoolean+37h (07FF7444C8FD7h)] 00007FF744D9F1F0 jmp __catch$?ConvertToBoolean@ @ YA_NAEBV?$basic_string@DU ?$char_traits@D @ std@ @ V?$allocator@D @ 2@ @ std@ @@Z$0+5Eh (07FF744D9F1F9h) 118: } 119: } 00007FF744D9F1F2 lea rax,[ConvertToBoolean+35h (07FF7444C8FD5h)] 00007FF744D9F1F9 add rsp,28h 00007FF744D9F1FD pop rdi 00007FF744D9F1FE pop rbp 00007FF744D9F1FF ret