??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品va久久久久久久,99久久国产热无码精品免费,久久精品a亚洲国产v高清不卡http://www.shnenglu.com/API/category/16121.htmlzh-cnFri, 31 Jul 2015 23:42:59 GMTFri, 31 Jul 2015 23:42:59 GMT60异常和异常处理(windowsq_Q?/title><link>http://www.shnenglu.com/API/archive/2014/11/26/208965.html</link><dc:creator>C++技术中?/dc:creator><author>C++技术中?/author><pubDate>Wed, 26 Nov 2014 07:12:00 GMT</pubDate><guid>http://www.shnenglu.com/API/archive/2014/11/26/208965.html</guid><wfw:comment>http://www.shnenglu.com/API/comments/208965.html</wfw:comment><comments>http://www.shnenglu.com/API/archive/2014/11/26/208965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/API/comments/commentRss/208965.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/API/services/trackbacks/208965.html</trackback:ping><description><![CDATA[<div>【翻译】异常和异常处理Qwindowsq_Q?/div><div>译的不好,莫怪?/div><div>原文地址Q?http://crashrpt.sourceforge.net/docs/html/exception_handling.html#getting_exception_context</div><div>About Exceptions and Exception Handling</div><div></div><div>About Exception</div><div></div><div>当程序遇C个异常或一个严重的错误Ӟ通常意味着它不能l正常运行ƈ且需要停止执行?/div><div>例如Q当遇到下列情况ӞE序会出现异常:</div><div>  E序讉K一个不可用的内存地址Q例如,NULL指针Q;</div><div>l 无限递归D的栈溢出Q?/div><div>l 向一个较的~冲区写入较大块的数据;</div><div>l cȝU虚函数被调用;</div><div>l 甌内存p|Q内存空间不IQ?/div><div>l 一个非法的参数被传递给C++函数Q?/div><div>l Cq行时库到一个错误ƈ且需要程序终止执行?/div><div> </div><div>有两U不同性质的异常:l构化异?Structured Exception Handling, SEH)和类型化的C++异常?/div><div>SEH是ؓC语言设计的,但是他们也能够被用于C++。SEH异常由__try{}__except(){}l构来处理。SEH是VC++~译器特有的Q因此如果你惌~写可移植的代码Q就不应当用SEH?/div><div>C++中类型化的异常是由try{}catch(){}l构处理的。例如(例子来自q里http://www.cplusplus.com/doc/tutorial/exceptions/Q:</div><div></div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> #include <iostream><br /> <span style="color: #0000FF; ">using</span> <span style="color: #0000FF; ">namespace</span> std;<br />  <br /> <span style="color: #0000FF; ">int</span> main(){<br />     <span style="color: #0000FF; ">try</span>{<br />        <span style="color: #0000FF; ">throw</span> 20;<br />     }<br />     <span style="color: #0000FF; ">catch</span> (<span style="color: #0000FF; ">int</span> e){<br />        cout << "An exception occrred. Exception Nr. " << e << endl;<br />     }<br />  <br />     <span style="color: #0000FF; ">return</span> 0;<br /> }</div></div><div> </div><div>l构化异常处?/div><div></div><div>当发生一个SEH异常Ӟ你通常会看C个意囑֐微Y发送错误报告的弹出H口?/div><div>你可以用RaiseException()函数自己产生一个SEH异常?/div><div>你可以在你的代码中用__try{}__except(Expression){}l构来捕获SEH异常。程序中的main()函数被这Ll构保护Q因此默认地Q所有未被处理的SEH异常都会被捕莗?/div><div>例如Q?/div><div></div><div> <span style="background-color: #eeeeee; font-size: 13px;">#include </span><span style="background-color: #eeeeee; font-size: 13px;"><</span><span style="background-color: #eeeeee; font-size: 13px;">Windows.h</span><span style="background-color: #eeeeee; font-size: 13px;">></span></div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all">  <br /> <span style="color: #0000FF; ">int</span> main(){<br />     <span style="color: #0000FF; ">int</span> *p = NULL;  <span style="color: #008000; ">//</span><span style="color: #008000; "> pointer to NULL</span><span style="color: #008000; "><br /></span>     __try{<br />        <span style="color: #008000; ">//</span><span style="color: #008000; "> Guarded code</span><span style="color: #008000; "><br /></span>        *p = 13;    <span style="color: #008000; ">//</span><span style="color: #008000; "> causes an access violation exception;</span><span style="color: #008000; "><br /></span>     }<br />     __except(EXCEPTION_EXECUTE_HANDLER){  <span style="color: #008000; ">//</span><span style="color: #008000; "> Here is exception filter expression<br />        </span><span style="color: #008000; ">//</span><span style="color: #008000; "> Here is exception handler<br />        </span><span style="color: #008000; ">//</span><span style="color: #008000; "> Terminate program</span><span style="color: #008000; "><br /></span>        ExitProcess(1);<br />     }<br />  <br />     <span style="color: #0000FF; ">return</span> 0;<br /> }</div><div></div><div> </div><div> </div><div>每一个SEH异常都有一个与其相兌的异常码Qexception codeQ。你可以使用GetExceptionCode()函数来获取异常码。你可以通过GetExceptionInformation()来获取异怿息。ؓ了用这些函敎ͼ你通常会像下面CZ中一样定制自qexception filter?/div><div>下面的例子说明了如何使用SEH exception filter?/div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br /> <span style="color: #0000FF; ">int</span> seh_filter(unsigned <span style="color: #0000FF; ">int</span> code, <span style="color: #0000FF; ">struct</span> _EXCEPTION_POINTERS *ep){<br />     <span style="color: #008000; ">//</span><span style="color: #008000; "> Generate error report<br />     </span><span style="color: #008000; ">//</span><span style="color: #008000; "> Execute exception handler</span><span style="color: #008000; "><br /></span>     <span style="color: #0000FF; ">return</span> EXCEPTION_EXECUTE_HANDLER;<br /> }<br />  <br /> <span style="color: #0000FF; ">int</span> main(){<br />     __try{<br />        <span style="color: #008000; ">//</span><span style="color: #008000; "> .. some buggy code here</span><span style="color: #008000; "><br /></span>     }<br />     __except(seh_filter(GetExceptionCode(), GetExceptionInformation())){<br />        <span style="color: #008000; ">//</span><span style="color: #008000; "> Terminate program</span><span style="color: #008000; "><br /></span>        ExitProcess(1);<br />     }<br />  <br />     <span style="color: #0000FF; ">return</span> 0;<br /> }</div></div><div></div><div> </div><div> </div><div>__try{}__exception(){}l构是面向C语言的,但是Q你可以一个SEH异常重定向到C++异常Qƈ且你可以像处理C++异常一样处理它。我们可以用C++q行时库中的_set_se_translator()函数来实现?/div><div>看一个MSDN中的例子Q译者注Q运行此例子需打开/EHa~译选项Q:</div><div></div><div> <span style="background-color: #eeeeee; font-size: 13px;">  #include </span><span style="background-color: #eeeeee; font-size: 13px;"><</span><span style="background-color: #eeeeee; font-size: 13px;">cstdio</span><span style="background-color: #eeeeee; font-size: 13px;">></span></div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all">   #include <windows.h><br />   #include <eh.h><br />    <br />   <span style="color: #0000FF; ">void</span> SEFunc();<br />   <span style="color: #0000FF; ">void</span> trans_func(unsigned <span style="color: #0000FF; ">int</span>, EXCEPTION_POINTERS *);<br />    <br />   <span style="color: #0000FF; ">class</span> SE_Exception{<br />   <span style="color: #0000FF; ">private</span>:<br />       unsigned <span style="color: #0000FF; ">int</span> nSE;<br />   <span style="color: #0000FF; ">public</span>:<br />       SE_Exception(){}<br />       SE_Exception(unsigned <span style="color: #0000FF; ">int</span> n) : nSE(n){}<br />       ~SE_Exception() {}<br />       unsigned <span style="color: #0000FF; ">int</span> getSeNumber(){ <span style="color: #0000FF; ">return</span> nSE; }<br />   };<br />    <br />   <span style="color: #0000FF; ">int</span> main(<span style="color: #0000FF; ">void</span>){<br />       <span style="color: #0000FF; ">try</span>{<br />          _set_se_translator(trans_func);<br />          SEFunc();<br />       }<br />       <span style="color: #0000FF; ">catch</span>(SE_Exception e){<br />          printf("Caught a __try exception with SE_Exception.\n");<br />       }<br />   }<br />    <br />   <span style="color: #0000FF; ">void</span> SEFunc(){<br />       __try{<br />          <span style="color: #0000FF; ">int</span> x, y=0;<br />          x = 5 / y;<br />       }<br />       __finally{<br />          printf("In finally\n");<br />       }<br />   }<br />    <br />   <span style="color: #0000FF; ">void</span> trans_func(unsigned <span style="color: #0000FF; ">int</span> u, EXCEPTION_POINTERS* pExp){<br />       printf("In trans_func.\n");<br />       <span style="color: #0000FF; ">throw</span> SE_Exception();<br />   }</div><div></div><div> </div><div> </div><div>你可能忘记对一些潜在的错误代码使用__try{}__catch(Expression){}l构q行保护Q而这些代码可能会产生异常Q但是这个异常却没有被你的程序所处理。不用担心,q个未被处理的SEH异常能够被unhandled Exception filter所捕获Q我们可以用SetUnhandledExceptionFilter()函数讄top-levelunhandled exception filter?/div><div>异常信息Q异常发生时的CPU状态)通过EXCEPTION_POINTERS被传递给exception handler?/div><div>例如Q?/div><div></div><div> <span style="background-color: #eeeeee; font-size: 13px;">  </span><span style="font-size: 13px; color: #008000;">//</span><span style="font-size: 13px; color: #008000;"> crt_settrans.cpp</span></div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #008000; ">   </span><span style="color: #008000; ">//</span><span style="color: #008000; "> compile with: /EHa</span><span style="color: #008000; "><br /></span>   LONG WINAPI MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionPtrs){<br />       <span style="color: #008000; ">//</span><span style="color: #008000; "> Do something, for example generate error report<br />       </span><span style="color: #008000; ">//</span><span style="color: #008000; ">..<br />       </span><span style="color: #008000; ">//</span><span style="color: #008000; "> Execute default exception handler next</span><span style="color: #008000; "><br /></span>       <span style="color: #0000FF; ">return</span> EXCEPTION_EXECUTE_HANDLER;<br />   }<br />    <br />   <span style="color: #0000FF; ">void</span> main(){<br />       SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);<br />       <span style="color: #008000; ">//</span><span style="color: #008000; "> .. some unsafe code here</span><span style="color: #008000; "><br /></span>   }</div><div></div><div> </div><div> </div><div>top-level SEH exception handler对进E中的每个线E都起作用,因此在你的main()函数开头调用一ơ就够了?/div><div>top-level SEH exception handler在发生异常的U程的上下文中被调用。这会媄响异常处理函C异常中恢复的能力?/div><div>如果你的异常处理函数位于一个DLL中,那么在用SetUnhandledExceptionFilter()函数时就要小心了。如果你的函数在E序崩溃时还未被加蝲Q这U行为是不可预测的?/div><div>向量化异常处理(Vectored Exception HandlingQ?/div><div></div><div>向量化异常处?VEH)是结构化异常处理的一个扩展,它在Windows XP中被引入?/div><div>你可以用AddVectoredExceptionHandler()函数d一个向量化异常处理器,VEH的缺Ҏ它只能用在WinXP及其以后的版本,因此需要在q行时检查AddVectoredExceptionHandler()函数是否存在?/div><div>要移除先前安装的异常处理器,可以使用RemoveVectoredExceptionHandler()函数?/div><div>VEH允许查看或处理应用程序中所有的异常。ؓ了保持后向兼容,当程序中的某些部分发生SEH异常Ӟpȝ依次调用已安装的VEH处理器,直到它找到有用的SEH处理器?/div><div>VEH的一个优Ҏ能够链接异常处理?chain exception handlers)Q因此如果有人在你之前安装了向量化异常处理器Q你仍然能截莯些异常?/div><div>当你需要像调试器一L事所有的异常Ӟ使用VEH是很合适的。问题是你需要决定哪个异帔R要处理,哪个异常需要蟩q?In program's code, some exceptions may be intentionally guarded by __try{}__except(){} construction, and handling such exceptions in VEH and not passing it to frame-based SEH handler, you may introduce bugs into application logics.</div><div>VEH目前没有被CrashRpt所使用。SetUnhandledExceptionFilter()更加适用Q因为它是top-level SEH处理器。如果没有h处理异常Qtop-level SEH处理器就会被调用Qƈ且你不用军_是否要处理这个异常?/div><div>CRT 错误处理</div><div></div><div>除了SEH异常和C++cd化异常,Cq行?C runtime libraries, CRT)也提供它自己的错误处理机Ӟ在你的程序中也应该考虑使用它?/div><div>当CRT遇到一个未被处理的C++cd化异常时Q它会调用terminate()函数。如果你x截这个调用ƈ提供合适的行ؓQ你应该使用set_terminate()函数讄错误处理?error hanlder)。例如:</div><div></div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->   #include <iostream><br />   <span style="color: #0000FF; ">void</span> my_terminate_handler()<br />   {<br />       <span style="color: #008000; ">//</span><span style="color: #008000; "> Abnormal program termination (terminate() function was called)<br />       </span><span style="color: #008000; ">//</span><span style="color: #008000; "> Do something here<br />       </span><span style="color: #008000; ">//</span><span style="color: #008000; "> Finally, terminate program</span><span style="color: #008000; "><br /></span>       std::cout << "terminate.\n";<br />       exit(1);<br />   }<br />    <br />   <span style="color: #0000FF; ">int</span> main()<br />   {<br />       set_terminate(my_terminate_handler);<br />    <br />       terminate();<br />    <br />       <span style="color: #0000FF; ">return</span> 0;<br />   }</div></div><div></div><div> </div><div> </div><div>NoteQ在多线E环境中Q每个线E维护各自的unexpected和terminate函数。每个新U程需要安装自qunexpected和terminate函数。因此,每个U程负责自己的unexpected和terminate处理器?/div><div> </div><div>使用_set_purecall_handler()函数来处理纯虚函数调用。这个函数可以用于VC++2003及其后箋版本。这个函数可以用于一个进E中的所有线E。例如(来源于MSDNQ:</div><div></div><div>  <span style="background-color: #eeeeee; font-size: 13px;"> </span><span style="font-size: 13px; color: #008000;">//</span><span style="font-size: 13px; color: #008000;"> compile with: /EHa</span></div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #008000; ">   </span><span style="color: #008000; ">//</span><span style="color: #008000; "> _set_purecall_handler.cpp<br />   </span><span style="color: #008000; ">//</span><span style="color: #008000; "> compile with: /W1</span><span style="color: #008000; "><br /></span>   #include <tchar.h><br />   #include <stdio.h><br />   #include <stdlib.h><br />    <br />   <span style="color: #0000FF; ">class</span> CDerived;<br />   <span style="color: #0000FF; ">class</span> CBase{<br />   <span style="color: #0000FF; ">public</span>:<br />       CBase(CDerived *derived): m_pDerived(derived) {};<br />       ~CBase();<br />       <span style="color: #0000FF; ">virtual</span> <span style="color: #0000FF; ">void</span> function(<span style="color: #0000FF; ">void</span>) = 0;<br />    <br />       CDerived * m_pDerived;<br />   };<br />    <br />   <span style="color: #0000FF; ">class</span> CDerived : <span style="color: #0000FF; ">public</span> CBase{<br />   <span style="color: #0000FF; ">public</span>:<br />       CDerived() : CBase(<span style="color: #0000FF; ">this</span>) {};   <span style="color: #008000; ">//</span><span style="color: #008000; "> C4355</span><span style="color: #008000; "><br /></span>       <span style="color: #0000FF; ">virtual</span> <span style="color: #0000FF; ">void</span> function(<span style="color: #0000FF; ">void</span>) {};<br />   };<br />    <br />   CBase::~CBase(){<br />       m_pDerived -> function();<br />   }<br />    <br />   <span style="color: #0000FF; ">void</span> myPurecallHandler(<span style="color: #0000FF; ">void</span>){<br />       printf("In _purecall_handler.");<br />       exit(0);<br />   }<br />    <br />   <span style="color: #0000FF; ">int</span> _tmain(<span style="color: #0000FF; ">int</span> argc, _TCHAR* argv[]){<br />       <span style="color: #008000; ">//</span><span style="color: #008000; ">_set_purecall_handler(myPurecallHandler);</span><span style="color: #008000; "><br /></span>       CDerived myDerived;<br />   }</div><div></div><div> </div><div> </div><div>使用_set_new_handler()函数处理内存分配p|。这个函数能够用于VC++2003及其后箋版本。这个函数可以用于一个进E中的所有线E。也可以考虑使用_set_new_mode()函数来ؓmalloc()函数定义错误时的行ؓ。例如(来自MSDNQ:</div><div></div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->  <span style="color: #008000; ">//</span><span style="color: #008000; "> crt_settrans.cpp</span><span style="color: #008000; "><br /></span>  #include <<span style="color: #0000FF; ">new</span>.h><br />  <span style="color: #0000FF; ">int</span> handle_program_memory_depletion( size_t ){<br />      <span style="color: #008000; ">//</span><span style="color: #008000; "> Your code</span><span style="color: #008000; "><br /></span>  }<br />  <span style="color: #0000FF; ">int</span> main( <span style="color: #0000FF; ">void</span> ){<br />      _set_new_handler( handle_program_memory_depletion );<br />      <span style="color: #0000FF; ">int</span> *pi = <span style="color: #0000FF; ">new</span> <span style="color: #0000FF; ">int</span>[BIG_NUMBER];<br />  }</div></div><div></div><div> </div><div> </div><div>在VC++2003中,你能够用_set_security_error_handler()函数来处理缓冲区溢出错误。这个函数已l被废弃Qƈ且从之后VC++版本的CRT中移除?/div><div>当系l函数调用检到非法的参数时Q会使用_set_invalid_parameter_handler()函数来处理这U情c这个函数能够用于VC++2005及其以后的版本。这个函数可用于q程中的所有线E?/div><div>例子Q来源于MSDNQ:</div><div></div><div>  <span style="background-color: #eeeeee; font-size: 13px;"> </span><span style="font-size: 13px; color: #008000;">//</span><span style="font-size: 13px; color: #008000;"> compile with: /Zi /MTd</span></div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all">   #include <stdio.h><br />   #include <stdlib.h><br />   #include <crtdbg.h>  <span style="color: #008000; ">//</span><span style="color: #008000; "> For _CrtSetReportMode</span><span style="color: #008000; "><br /></span>    <br />   <span style="color: #0000FF; ">void</span> myInvalidParameterHandler(<span style="color: #0000FF; ">const</span> wchar_t* expression,<br />                               <span style="color: #0000FF; ">const</span> wchar_t* function,<br />                               <span style="color: #0000FF; ">const</span> wchar_t* file,<br />                               unsigned <span style="color: #0000FF; ">int</span> line,<br />                               uintptr_t pReserved){<br />       wprintf(L"Invalid parameter detected in function %s."<br />          L" File: %s Line: %d\n", function, file, line);<br />       wprintf(L"Expression: %s\n", expression);<br />   }<br />    <br />    <br />   <span style="color: #0000FF; ">int</span> main( ){<br />       <span style="color: #0000FF; ">char</span>* formatString;<br />    <br />       _invalid_parameter_handler oldHandler, newHandler;<br />       newHandler = myInvalidParameterHandler;<br />       oldHandler = _set_invalid_parameter_handler(newHandler);<br />    <br />       <span style="color: #008000; ">//</span><span style="color: #008000; "> Disable the message box for assertions.</span><span style="color: #008000; "><br /></span>       _CrtSetReportMode(_CRT_ASSERT, 0);<br />    <br />       <span style="color: #008000; ">//</span><span style="color: #008000; "> Call printf_s with invalid parameters.</span><span style="color: #008000; "><br /></span>       formatString = NULL;<br />       printf(formatString);<br />       <span style="color: #0000FF; ">return</span> 0;<br />   }</div><div></div><div> </div><div> </div><div>C++信号处理C++ Singal Handling</div><div></div><div>C++提供了被UCؓ信号的中断机制。你可以使用signal()函数处理信号?/div><div>Visual C++提供?中类型的信号Q?/div><div>l SIGABRT Abnormal termination</div><div>l SIGFPE Floating-point error</div><div>l SIGILL Illegal instruction</div><div>l SIGINT CTRL+C signal</div><div>l SIGSEGV Illegal storage access</div><div>l SIGTERM</div><div>MSDN中说SIGILL, SIGSEGV,和SIGTERM are not generated under Windows NTq且与ANSI相兼宏V但是,如果你在ȝE中讄SIGSEGV signal handlerQCRT会调用它,而不是调用SetUnhandledExceptionFilter()函数讄的SHE exception handlerQ全局变量_pxcptinfoptrs中包含了指向异常信息的指针?/div><div>_pxcptinfoptrs也会被用于SIGFPE handler中,而在所有其他的signal handlers中,它将会被设ؓNULL?/div><div>当一个floating point 错误发生Ӟ例如除零错,CRT调用SIGFPE signal handler。然而,默认情况下,不会产生float point 异常Q取而代之的是,会产生一个NaN或无I大的数作ؓq种点数运的l果。可以用_controlfp_s()函数使得~译器能够生floating point异常?/div><div>使用raise()函数Q你可以人工C生所有的6中信受例如:</div><div></div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->   #include <cstdlib><br />   #include <csignal><br />   #include <iostream><br />    <br />   <span style="color: #0000FF; ">void</span> sigabrt_handler(<span style="color: #0000FF; ">int</span>){<br />       <span style="color: #008000; ">//</span><span style="color: #008000; "> Caught SIGABRT C++ signal<br />       </span><span style="color: #008000; ">//</span><span style="color: #008000; "> Terminate program</span><span style="color: #008000; "><br /></span>            std::cout << "handled.\n";<br />            exit(1);<br />   }<br />    <br />   <span style="color: #0000FF; ">int</span> main(){<br />     signal(SIGABRT, sigabrt_handler);<br />     <span style="color: #008000; ">//</span><span style="color: #008000; "> Cause abort</span><span style="color: #008000; "><br /></span>     abort();   <br />   } </div></div><div></div><div> </div><div>Note:</div><div>虽然MSDN中没有详l地说明Q但是你应该ZE序中的每个U程都安装SIGFPE, SIGILL和SIGSEGV signal hanlders。SIGABRT, SIGINT和SIGTERM signal hanlders对程序中的每个线E都起作用,因此你只需要在你的main函数中安装他们一ơ就够了?/div><div>获取异常信息 Retrieving Exception Information</div><div></div><div>译者注Q这一节不太懂,以后有时间再译</div><div>When an exception occurs you typically want to get the CPU state to determine the place in your code that caused the problem. You use the information to debug the problem. The way you retrieve the exception information differs depending on the exception handler you use.</div><div>In the SEH exception handler set with the SetUnhandledExceptionFilter() function, the exception information is retrieved from EXCEPTION_POINTERS structure passed as function parameter.</div><div> </div><div>In __try{}__catch(Expression){} construction you retrieve exception information using GetExceptionInformation() intrinsic function and pass it to the SEH exception filter function as parameter.</div><div> </div><div>In the SIGFPE and SIGSEGV signal handlers you can retrieve the exception information from the _pxcptinfoptrs global CRT variable that is declared in <signal.h>. This variable is not documented well in MSDN.</div><div> </div><div>In other signal handlers and in CRT error handlers you have no ability to easily extract the exception information. I found a workaround used in CRT code (see CRT 8.0 source files, invarg.c, line 104).</div><div> </div><div>The following code shows how to get current CPU state used as exception information.</div><div></div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->   <span style="color: #0000FF; ">#if</span> _MSC_VER>=1300<br />   #include <rtcapi.h><br />   <span style="color: #0000FF; ">#endif</span><br />   <br />   #ifndef _AddressOfReturnAddress<br />   <br />   <span style="color: #008000; ">//</span><span style="color: #008000; "> Taken from: </span><span style="color: #008000; text-decoration: underline; ">http://msdn.microsoft.com/en-us/library/s975zw7k</span><span style="color: #008000; ">(VS.71).aspx</span><span style="color: #008000; "><br /></span>   #ifdef __cplusplus<br />   <span style="color: #0000FF; ">#define</span> EXTERNC extern "C"<br />   <span style="color: #0000FF; ">#else</span><br />   <span style="color: #0000FF; ">#define</span> EXTERNC<br />   <span style="color: #0000FF; ">#endif</span><br />   <br />   <span style="color: #008000; ">//</span><span style="color: #008000; "> _ReturnAddress and _AddressOfReturnAddress should be prototyped before use </span><span style="color: #008000; "><br /></span>   EXTERNC <span style="color: #0000FF; ">void</span> * _AddressOfReturnAddress(<span style="color: #0000FF; ">void</span>);<br />   EXTERNC <span style="color: #0000FF; ">void</span> * _ReturnAddress(<span style="color: #0000FF; ">void</span>);<br />   <br />   <span style="color: #0000FF; ">#endif</span> <br />   <br />   <span style="color: #008000; ">//</span><span style="color: #008000; "> The following function retrieves exception info</span><span style="color: #008000; "><br /></span>   <br />   <span style="color: #0000FF; ">void</span> GetExceptionPointers(DWORD dwExceptionCode, <br />                             EXCEPTION_POINTERS** ppExceptionPointers)<br />   {<br />       <span style="color: #008000; ">//</span><span style="color: #008000; "> The following code was taken from VC++ 8.0 CRT (invarg.c: line 104)</span><span style="color: #008000; "><br /></span>   <br />       EXCEPTION_RECORD ExceptionRecord;<br />       CONTEXT ContextRecord;<br />       memset(&ContextRecord, 0, <span style="color: #0000FF; ">sizeof</span>(CONTEXT));<br />   <br />   #ifdef _X86_<br />   <br />       __asm {<br />           mov dword ptr [ContextRecord.Eax], eax<br />               mov dword ptr [ContextRecord.Ecx], ecx<br />               mov dword ptr [ContextRecord.Edx], edx<br />               mov dword ptr [ContextRecord.Ebx], ebx<br />               mov dword ptr [ContextRecord.Esi], esi<br />               mov dword ptr [ContextRecord.Edi], edi<br />               mov word ptr [ContextRecord.SegSs], ss<br />               mov word ptr [ContextRecord.SegCs], cs<br />               mov word ptr [ContextRecord.SegDs], ds<br />               mov word ptr [ContextRecord.SegEs], es<br />               mov word ptr [ContextRecord.SegFs], fs<br />               mov word ptr [ContextRecord.SegGs], gs<br />               pushfd<br />               pop [ContextRecord.EFlags]<br />       }<br />   <br />       ContextRecord.ContextFlags = CONTEXT_CONTROL;<br />   #pragma warning(push)<br />   #pragma warning(disable:4311)<br />       ContextRecord.Eip = (ULONG)_ReturnAddress();<br />       ContextRecord.Esp = (ULONG)_AddressOfReturnAddress();<br />   #pragma warning(pop)<br />       ContextRecord.Ebp = *((ULONG *)_AddressOfReturnAddress()-1);<br />   <br />   <br />   <span style="color: #0000FF; ">#elif</span> defined (_IA64_) || defined (_AMD64_)<br />   <br />       <span style="color: #008000; ">/*</span><span style="color: #008000; "> Need to fill up the Context in IA64 and AMD64. </span><span style="color: #008000; ">*/</span><br />       RtlCaptureContext(&ContextRecord);<br />   <br />   <span style="color: #0000FF; ">#else</span>  /* defined (_IA64_) || defined (_AMD64_) */<br />   <br />       ZeroMemory(&ContextRecord, <span style="color: #0000FF; ">sizeof</span>(ContextRecord));<br />   <br />   <span style="color: #0000FF; ">#endif</span>  /* defined (_IA64_) || defined (_AMD64_) */<br />   <br />       ZeroMemory(&ExceptionRecord, <span style="color: #0000FF; ">sizeof</span>(EXCEPTION_RECORD));<br />   <br />       ExceptionRecord.ExceptionCode = dwExceptionCode;<br />       ExceptionRecord.ExceptionAddress = _ReturnAddress();<br />   <br />   <br />       EXCEPTION_RECORD* pExceptionRecord = <span style="color: #0000FF; ">new</span> EXCEPTION_RECORD;<br />       memcpy(pExceptionRecord, &ExceptionRecord, <span style="color: #0000FF; ">sizeof</span>(EXCEPTION_RECORD));<br />       CONTEXT* pContextRecord = <span style="color: #0000FF; ">new</span> CONTEXT;<br />       memcpy(pContextRecord, &ContextRecord, <span style="color: #0000FF; ">sizeof</span>(CONTEXT));<br />   <br />       *ppExceptionPointers = <span style="color: #0000FF; ">new</span> EXCEPTION_POINTERS;<br />       (*ppExceptionPointers)->ExceptionRecord = pExceptionRecord;<br />       (*ppExceptionPointers)->ContextRecord = pContextRecord;  <br />   }</div></div><div></div><div>Visual C++ Complier Flags</div><div></div><div>Visual C++~译器中有一些编译选项和异常处理有兟?/div><div>在Project Properties->Configuration Properties->C/C++ ->Code Generation中可以找到这些选项?/div><div>异常处理模型Exception Handling Model</div><div>你可以ؓVC++~译器选择异常处理模型。选项/EHs(或者EHsc)用来指定同步异常处理模型Q?EHa用来指定异步异常处理模型。可以查看下面参考小节的"/EH(Exception Handling Model)"以获取更多的信息?/div><div>Floating Point Exceptions</div><div>你可以?fp:except~译选项打开float point exceptions?/div><div>~冲区安全检查Buffer Security Checks</div><div>你可以?GS(Buffer Security Check)选项来强制编译器插入代码以检查缓冲区溢出。缓冲区溢出指的是一大块数据被写入一块较的~冲Z。当到~冲区溢出,CRT calls internal security handler that invokes Watson directly?/div><div>Note:</div><div>在VC++(CRT7.1)中,~冲区溢到ӞCRT会调用由_set_security_error_handler函数讄的处理器。然而,在之后的VC版本中这个函数被废弃?/div><div>从CRT8.0开始,你在你的代码中不能截获安全错误。当~冲区溢到ӞCRT会直接请求WatsonQ而不是调用unhandled exception filter。这样做是由于安全原因ƈ且微软不打算改变q种行ؓ?/div><div>更多的信息请参考如下链?/div><div>https://connect.microsoft.com/VisualStudio/feedback/details/101337/a-proposal-to-make-dr-watson-invocation-configurable</div><div>http://blog.kalmbachnet.de/?postid=75</div><div>异常处理和CRT链接Exception Handling and CRT Linkage</div><div></div><div>你的应用E序中的每个moduleQEXE, DLLQ都需要链接CRT。你可以CRT链接为多U程静态库(multi-threaded static library)或者多U程动态链接库(multi-threaded dynamic link library)。如果你讄了CRT error handlersQ例如你讄了terminate handler, unexcepted handler, pure call handler, invalid parameter handler, new operator error handler or a signal handlerQ那么他们将只在你链接的CRT上运行,q且不会捕获其他CRT模块中的异常Q如果存在的话)Q因为每个CRT模块都有它自q内部状态?/div><div>多个工程中的module可以׃nCRT DLL。这得被链接的CRT代码辑ֈ最化Qƈ且CRT DLL中的所有异帔R会被立刻处理。这也是推荐使用multi-threaded CRT DLL作ؓCRT链接方式的原因?/div><img src ="http://www.shnenglu.com/API/aggbug/208965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/API/" target="_blank">C++技术中?/a> 2014-11-26 15:12 <a href="http://www.shnenglu.com/API/archive/2014/11/26/208965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>panel和wxBoxSizerhttp://www.shnenglu.com/API/archive/2014/09/28/208442.htmlC++技术中?/dc:creator>C++技术中?/author>Sun, 28 Sep 2014 08:13:00 GMThttp://www.shnenglu.com/API/archive/2014/09/28/208442.htmlhttp://www.shnenglu.com/API/comments/208442.htmlhttp://www.shnenglu.com/API/archive/2014/09/28/208442.html#Feedback0http://www.shnenglu.com/API/comments/commentRss/208442.htmlhttp://www.shnenglu.com/API/services/trackbacks/208442.html//1.加入boxSizer19
    wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
    this->SetSizer(topSizer);
    
    

    wxPanel* upPanel = new wxPanel( this, ID_BOT_PANEL2 ,wxDefaultPosition, wxSize(800, 100));

    upPanel->SetBackgroundColour(*wxBLACK);//黑色背景

    wxPanel* centerPanel = new wxPanel( this, ID_BOT_PANEL3,wxDefaultPosition, wxSize(800, 100) );
    centerPanel->SetBackgroundColour(*wxWHITE);//白色背景

    wxPanel* bottomPanel = new wxPanel( this, ID_BOT_PANEL4, wxDefaultPosition, wxSize(800, 100));
    
    bottomPanel->SetBackgroundColour(*wxRED);//U色背景
    
    topSizer->Add(upPanel,
        1,                   //垂直方向可拉?/span>
        wxEXPAND|            //水^方向自动填充
        wxALL,               //四周都有Ҏ
        10                   //Ҏ宽度?0
        );

    
    topSizer->Add(centerPanel,0,wxEXPAND);
    topSizer->Add(bottomPanel,0,wxEXPAND);

]]>
关于warning C4819http://www.shnenglu.com/API/archive/2012/11/12/195056.htmlC++技术中?/dc:creator>C++技术中?/author>Mon, 12 Nov 2012 02:00:00 GMThttp://www.shnenglu.com/API/archive/2012/11/12/195056.htmlhttp://www.shnenglu.com/API/comments/195056.htmlhttp://www.shnenglu.com/API/archive/2012/11/12/195056.html#Feedback5http://www.shnenglu.com/API/comments/commentRss/195056.htmlhttp://www.shnenglu.com/API/services/trackbacks/195056.html~译VC++E序的时候出现如下提C告:

warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss

因ؓ只是一个warningQ不影响正常~译Q所以ƈ没有引v大家多大的关注。我一开始的时候也是如此。但是后来出现的ơ数多了Q发现这个警告和在程序Debug的时?br />无法停在断点Q刷刷刷pMҎ无法q行Debug。而罪祸首就是这个warningQ改正了q个warningpq行Debug了?/p>

下面讲述我是怎么消除q个警告的?/p>

q个警告的意思是Q在该文件中有一个或多个字符不是Unicode字符Q要求把q个字符变成Unicode字符?/p>

NQ在~译信息里ƈ没有提示是哪个字W,或者是在哪一行里出现的该字符。查找v来非常的难,甚至是不可能的Q务!

我在|络上找了好多资料都没有扑ֈ解决Ҏ。因为大安不注意这个不影响~译的警告。后来在一个国外的|站上找C解决的方法。很单,q个ҎҎ不需要知道具体是哪个字符在捣|

解决ҎQ打开出现warning的文ӞCtrl+A全选,然后在文件菜单:file->advanced save options Q在弹出的选项中选择新的~码方式为:UNICODE codepage 1200 Q点ȝ定,问题p决了?/p>

]]>
Memcache存储大数据的问题http://www.shnenglu.com/API/archive/2012/10/19/193536.htmlC++技术中?/dc:creator>C++技术中?/author>Fri, 19 Oct 2012 09:20:00 GMThttp://www.shnenglu.com/API/archive/2012/10/19/193536.htmlhttp://www.shnenglu.com/API/comments/193536.htmlhttp://www.shnenglu.com/API/archive/2012/10/19/193536.html#Feedback0http://www.shnenglu.com/API/comments/commentRss/193536.htmlhttp://www.shnenglu.com/API/services/trackbacks/193536.htmlMemcached存储单个item最大数据是?MB内,如果数据过1M,存取set和get是都是返回falseQ而且引v性能的问题?/span>

我们之前Ҏ行榜的数据进行缓存,׃排行榜在我们所有sql select查询里面占了30%Q而且我们排行榜每时更新一ơ,所以必d数据做缓存。ؓ了清除缓存方便,把所有的用户的数据放在同一key中,׃memcached:set的时候没有压~数据。在试服测试的时候,没发现问题,当上U的时候,l果发现Q在Uh数刚?90人的时候,服务器load average飘到7.9。然后我们去掉缓存,一下子׃降到0.59?/span>

所以Memcahce不适合~存大数据,过1MB的数?/span>Q可以考虑在客L压羃或拆分到多个key中。大的数据在q行load和uppack到内存的时候需要花很长旉Q从而降低服务器的性能?/span>

Memcached支持最大的存储对象?/span>1M。这个值由其内存分配机制决定的?/span>

memcached默认情况下采用了名ؓSlab Allocator的机制分配、管理内存。在该机制出C前,内存的分配是通过Ҏ有记录简单地q行malloc?/span>free来进行的。但是,q种方式会导致内存碎片,加重操作pȝ内存理器的负担Q最坏的情况下,会导致操作系l比memcachedq程本nq慢?/span>Slab Allocator是册问题而诞生的?span style="font-family: 宋体; font-size: 10.5pt">Slab Allocator的基本原理是按照预先规定的大,分配的内存分割成特定长度的块,以完全解军_存碎片问?

今天Q?012-03-16Q我们重新测试了memcached ::set的数据大。可能是我们用php的memcached扩展是最新版Qset数据的时候是默认压羃的。set 数据Q?/span>

  1. $ac = new memcahed();
  2. $data = str_repeat('a', 1024* 1024); //1M的数?
  3. $r = $ac->set('key', $data, 9999);
  4. //或?
  5. $data = str_repeat('a', 1024* 1024*100);//100M的数?
  6. $r = $ac->set('key', $data, 9999);

 

 

 

不论?M的数据还?00M的数据,都能set成功。后来我发现Qmemcachedset数据的时候是默认压羃的。由于这个这个是重复的字W串Q压~率高达1000倍。因?00M的数据压~后实际也就100k而已?/span>

当我讄Q?/span>

  1. $ac->setOption(memcahed::OPT_COMPRESSION,0); //不压~存储数据?
  2. $data = str_repeat('a', 1024* 1024); //1M数据
  3. $r = $ac->set('key', $data, 9999);//1M的数据set不成功?