At present, it seems that it is relatively simple and has tried a more practical method to generate minidump. Let's take a look at it. Thanks to the original author.
Setunhandledexceptionfilter Function Learning: the operating system exception handling service routine will check whether the current process is in the debugging status
If yes, the debugger is notified of an exception. If not, the operating system will check whether the current thread has installed the exception frame chain (FS [0]). if Seh (try .... catch ....), then, seh is called and the global expansion of the active part is determined based on the returned results. If all seh in the exception chain does not handle this exception and the process is still debugging, the operating system will again notify the debugger of an exception (secondary exception ). If no one has processed it yet, the default Exception Handling Code unhandledexceptionhandler of the operating system is called. However, the operating system allows you to hook this function, which is set through the setunhandledexceptionfilter function. Most exceptions can be captured through this method, but stack overflow and coverage may not be captured. What can't be captured? It's done through the following methods !!!
I. Application of setunhandledexceptionfilter function in vs2005
Http://blog.csdn.net/happyhell/archive/2009/10/24/4723300.aspx
Many software sets their own exception capture functions to capture unprocessed exceptions and generate reports or logs (for example, generate a mini-dump file) to track bugs in the release version. However, in vs2005 (vc8), Microsoft has made some security-related changes to some CRT (C Runtime Library) code, which is typical, for example, a buffer overflow check is added. When an error occurs in the new CRT version, the exception is forcibly thrown to the default debugger (if no configuration is available, the default value is dr. watson), instead of notifying the exception capture function set by the application, this behavior mainly occurs in the following three cases.
(1) Call the abort function and set the _ call_reportfault option (this option is set by default in the release version ).
(2) Enable the runtime security check option and check for security errors during software running, such as cache overflow. (The security check option/Gs is enabled by default)
(3) The _ invalid_parameter error is encountered, and the application does not actively call the _ set_invalid_parameter_handler setting error capture function.
Therefore, the conclusion is that many errors cannot be captured in setunhandledexceptionfilter for programs compiled using vs2005 (vc8. This is a big change in CRT compared to the previous version, but unfortunately, Microsoft did not explicitly state it in the relevant documentation.
The reason why the application cannot catch those exceptions is that the new CRT Implementation Force deletes all capture functions previously set by the application in exception handling, as shown below:
/* Make sure any filter already in place is deleted .*/
Setunhandledexceptionfilter (null );
Unhandledexceptionfilter (& exceptionpointers );
The solution is to intercept the CRT and call the setunhandledexceptionfilter function to make it invalid. On the X86 platform, you can use the following code.
# Ifndef _ m_ix86
# Error "the following code only works for x86! "
# Endif
Void disablesetunhandledexceptionfilter ()
{
Void * ADDR = (void *) getprocaddress (loadlibrary (_ T ("kernel32.dll ")),
"Setunhandledexceptionfilter ");
If (ADDR)
{
Unsigned char code [16];
Int size = 0;
Code [size ++] = 0x33;
Code [size ++] = 0xc0;
Code [size ++] = 0xc2;
Code [size ++] = 0x04;
Code [size ++] = 0x00;
DWORD dwoldflag, dwtempflag;
Virtualprotect (ADDR, size, page_readwrite, & dwoldflag );
Writeprocessmemory (getcurrentprocess (), ADDR, code, size, null );
Virtualprotect (ADDR, size, dwoldflag, & dwtempflag );
}
}
After setting your own exception handling function, call disablesetunhandledexceptionfilter to disable CRT settings.
Call example:
Setunhandledexceptionfilter (myunhandledexceptionfilter );
Disablesetunhandledexceptionfilter ();
Myunhandledexceptionfilter is a self-implemented processing function. For details, see the following section.
The above API hook is set to solve the exception capture problem on vs2005. Although this is not a "clean" solution, it is indeed the only simple and effective method at present.
You can also use _ set_abort_behavior (0, _ write_abort_msg | _ call_reportfault), signal (SIGABRT ,...), and _ set_invalid_parameter_handler (...) solution (1) (3), but for (2), setting the API hook is the only way.
Ii. Create a mini-Dump File
When a program error occurs, call the API function to write the mini-dump file. Overcome the disadvantages of the drwtsn32 and ntsd programs. To generate a mini-dump file, follow these steps:
# Include <dbghelp. h>
# Pragma comment (Lib, "dbghelp. lib ")
Long winapi myunhandledexceptionfilter (struct _ exception_pointers * lpexceptioninfo)
{
Tchar szprogrampath [max_path] = {0 };
If (getmodulefilename (null, szprogrampath, max_path ))
{
Lptstr lpslash = _ tcsrchr (szprogrampath ,'//');
If (lpslash)
{
* (Lpslash + 1) = '/0 ';
}
}
Tchar szdumpfile [max_path] = {0 };
_ Stprintf (szdumpfile, _ T ("% S % d. dmp"), szprogrampath, time (null ));
Tchar szreportfile [max_path] = {0 };
_ Stprintf (szreportfile, _ T ("%sbugreport.exe"), szprogrampath );
Handle hdumpfile = createfile (szdumpfile, generic_write, 0, null, create_always, file_attribute_normal, null );
Minidump_exception_information stminidumpexceptioninfo;
Stminidumpexceptioninfo. exceptionpointers = lpexceptioninfo;
Stminidumpexceptioninfo. threadid = getcurrentthreadid ();
Stminidumpexceptioninfo. clientpointers = true;
Minidumpwritedump (getcurrentprocess (), getcurrentprocessid (), hdumpfile,
Minidumpnormal, & stminidumpexceptioninfo, null, null );
Closehandle (hdumpfile );
: ShellExecute (null, null, szreportfile, szdumpfile, null, sw_hide );
// Use your own user-friendly UI prompt here
MessageBox (null, _ T ("program crashed, generate dump file and call bug report! "), _ T (" oops "), mb_ OK );
Return exception_execute_handler;
}
3. Use windbg to analyze the mini-Dump File
Use windbg to open the DMP file and you will be able to see the call stack when an error occurs.
Windbg http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx here
Download and install the latest version. The windbg installation process is as follows. Then open the menu file-> symbol file path and add the following:
SRV * C:/symbol_local * http://msdl.microsoft.com/download/symbols;c:/debug
SRV * C:/symbol_local * release (PDB file) can be placed in the DEBUG directory of drive C.
Windbg will display busy or retrieving for a period of time, and then you can see the detailed dump information.
Iv. Use vs2005 to debug dump files
Http://www.cppblog.com/woaidongmao/archive/2009/10/21/99135.html
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/colinchan/archive/2010/01/06/5140038.aspx
V. Provide function (supplemented by yourself) for invalid detection parameters during C runtime)
We know that Microsoft provides a series of new functions to replace insecure string processing functions in the C Runtime Library. The primary task of all security functions is to verify the parameter values passed to them. The items to be checked include the pointer not being null, the integer is within the valid range, the enumerated value is valid, and the buffer is sufficient to accommodate the result data. If any of these checks fails, assert is triggered in debug mode, and the application is automatically terminated in release mode.
The running result of the sample program debug mode is as follows:
Int _ tmain (INT argc, _ tchar * argv [])
{
Tchar szbuffer [5];
_ Tcscpy_s (szbuffer, _ countof (szbuffer), text ("Hello, China "));
Getchar ();
Return 0;
}
At the same time, we can find that the memory of szbuffer is modified as follows:
In fact, the C Runtime allows us to provide our own functions. In this way, when the parameter detection fails, this function will be called.
The function declaration is as follows:
Void invalidparameterhandler (const tchar * pszexpression, const tchar * pszfunction, const tchar * pszfile, unsigned int nline, uintptr_t preserved );
Pszexpression describes the possible function call failures in the C Runtime implementation code. pszfunction describes the wrong function name and pszfile describes the source code file of the function, nline describes the number of wrong rows.
Then we can use the function _ set_invalid_parameter_handler to register the handler. The Code is as follows:
_ Set_invalid_parameter_handler (invalidparameterhandler );
In this way, when the parameter detection fails, we will call our own function invalidparameterhandler. However, the assert error box still appears. To avoid this situation, we can call _ crtsetreportmode (_ crt_assert, 0); to disable all debug assert failed dialogs that may be triggered by C runtime.
The sample code is as follows:
# Ifdef _ Unicode
# DEFINE _ tcout wcout
# Else
# DEFINE _ tcout cout
# Endif
Void invalidparameterhandler (const tchar * pszexpression, const tchar * pszfunction, const tchar * pszfile, unsigned int nline, uintptr_t preserved)
{
_ Tcout <pszfunction <"error" <Endl;
}
Int _ tmain (INT argc, _ tchar * argv [])
{
# Ifdef _ Unicode
Wcout. imbue (locale (), "", lc_ctype ));
# Endif
_ Crtsetreportmode (_ crt_assert, 0 );
_ Set_invalid_parameter_handler (invalidparameterhandler );
Tchar szbuffer [5];
Errno_t err = _ tcscpy_s (szbuffer, _ countof (szbuffer), text ("Hello, China "));
If (s_ OK = ERR)
{
_ Tcout <szbuffer <Endl;
}
Getchar ();
Return 0;
}
The execution result is as follows: