_CrtSetReportHook
Installs a client-defined reporting function by hooking it into the C run-time debug reporting process (debug version only).
_CRT_REPORT_HOOK_CrtSetReportHook(_CRT_REPORT_HOOKreportHook );
Routine | Required Header | Compatibility |
_CrtSetReportHook | <crtdbg.h> | Win NT, Win 95 |
For additional compatibility information, see Compatibility in the Introduction.
Libraries
LIBCD.LIB | Single thread static library, debug version |
LIBCMTD.LIB | Multithread static library, debug version |
MSVCRTD.LIB | Import library for MSVCRTD.DLL, debug version |
Return Value
_CrtSetReportHook returns the previous client-defined reporting function.
Parameter
reportHook
New client-defined reporting function to hook into the C run-time debug reporting process
Remarks
_CrtSetReportHook allows an application to use its own reporting function into the C run-time debug library reporting process. As a result, whenever _CrtDbgReport is called to generate a debug report, the application’s reporting function is called first. This functionality enables an application to perform operations such as filtering debug reports so it can focus on specific allocation types or send a report to destinations not available by using _CrtDbgReport. When _DEBUG is not defined, calls to _CrtSetReportHook are removed during preprocessing.
The _CrtSetReportHook function installs the new client-defined reporting function specified in reportHook and returns the previous client-defined hook. The following example demonstrates how a client-defined report hook should be prototyped:
int YourReportHook( int reportType, char *message, int *returnValue );
where reportType
is the debug report type (_CRT_WARN, _CRT_ERROR, _CRT_ASSERT), message
is the fully assembled debug user message to be contained in the report, and returnValue
is the value specified by the client-defined reporting function that should be returned by _CrtDbgReport. See the _CrtSetReportMode function for a complete description of the available report types.
If the client-defined reporting function completely handles the debug message such that no further reporting is required, then the function should return TRUE. When the function returns FALSE, _CrtDbgReport will be called to generate the debug report using the current settings for the report type, mode, and file. In addition, by specifying the _CrtDbgReport return value in returnValue
, the application can also control whether a debug break occurs. See _CrtSetReportMode, _CrtSetReportFile, and _CrtDbgReport for a complete description of how the debug report is configured and generated.
For more information about other hook-capable run-time functions and writing your own client-defined hook functions, see Writing Your Own Debug Hook Functions.
Example
/*
* REPORT.C:
* In this program, calls are made to the _CrtSetReportMode,
* _CrtSetReportFile, and _CrtSetReportHook functions.
* The _ASSERT macros are called to evaluate their expression.
* When the condition fails, these macros print a diagnostic message
* and call _CrtDbgReport to generate a debug report and the
* client-defined reporting function is called as well.
* The _RPTn and _RPTFn group of macros are also exercised in
* this program, as an alternative to the printf function.
* When these macros are called, the client-defined reporting function
* takes care of all the reporting - _CrtDbgReport won't be called.
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <crtdbg.h>
/*
* Define our own reporting function.
* We'll hook it into the debug reporting
* process later using _CrtSetReportHook.
* Define a global int to keep track of
* how many assertion failures occur.
*/
int gl_num_asserts=0;
int OurReportingFunction( int reportType, char *userMessage, int *retVal )
{
/*
* Tell the user our reporting function is being called.
* In other words - verify that the hook routine worked.
*/
fprintf("Inside the client-defined reporting function.\n", STDOUT);
fflush(STDOUT);
/*
* When the report type is for an ASSERT,
* we'll report some information, but we also
* want _CrtDbgReport to get called -
* so we'll return TRUE.
* When the report type is a WARNing or ERROR,
* we'll take care of all of the reporting. We don't
* want _CrtDbgReport to get called -
* so we'll return FALSE.
*/
if (reportType == _CRT_ASSERT)
{
gl_num_asserts++;
fprintf("This is the number of Assertion failures that have occurred: %d \n", gl_num_asserts, STDOUT);
fflush(STDOUT);
fprintf("Returning TRUE from the client-defined reporting function.\n", STDOUT);
fflush(STDOUT);
return(TRUE);
} else {
fprintf("This is the debug user message: %s \n", userMessage, STDOUT);
fflush(STDOUT);
fprintf("Returning FALSE from the client-defined reporting function.\n", STDOUT);
fflush(STDOUT);
return(FALSE);
}
/*
* By setting retVal to zero, we are instructing _CrtDbgReport
* to continue with normal execution after generating the report.
* If we wanted _CrtDbgReport to start the debugger, we would set
* retVal to one.
*/
retVal = 0;
}
int main()
{
char *p1, *p2;
/*
* Hook in our client-defined reporting function.
* Every time a _CrtDbgReport is called to generate
* a debug report, our function will get called first.
*/
_CrtSetReportHook( OurReportingFunction );
/*
* Define the report destination(s) for each type of report
* we are going to generate. In this case, we are going to
* generate a report for every report type: _CRT_WARN,
* _CRT_ERROR, and _CRT_ASSERT.
* The destination(s) is defined by specifying the report mode(s)
* and report file for each report type.
* This program sends all report types to STDOUT.
*/
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
/*
* Allocate and assign the pointer variables
*/
p1 = malloc(10);
strcpy(p1, "I am p1");
p2 = malloc(10);
strcpy(p2, "I am p2");
/*
* Use the report macros as a debugging
* warning mechanism, similar to printf.
* Use the assert macros to check if the
* p1 and p2 variables are equivalent.
* If the expression fails, _ASSERTE will
* include a string representation of the
* failed expression in the report.
* _ASSERT does not include the
* expression in the generated report.
*/
_RPT0(_CRT_WARN, "\n\n Use the assert macros to evaluate the expression p1 == p2.\n");
_RPTF2(_CRT_WARN, "\n Will _ASSERT find '%s' == '%s' ?\n", p1, p2);
_ASSERT(p1 == p2);
_RPTF2(_CRT_WARN, "\n\n Will _ASSERTE find '%s' == '%s' ?\n", p1, p2);
_ASSERTE(p1 == p2);
_RPT2(_CRT_ERROR, "\n \n '%s' != '%s'\n", p1, p2);
free(p2);
free(p1);
return 0;
}
Output
Inside the client-defined reporting function.
This is the debug user message: Use the assert macros to evaluate the expression p1 == p2
Returning FALSE from the client-defined reporting function.
Inside the client-defined reporting function.
This is the debug user message: dbgmacro.c(54) : Will _ASSERT find 'I am p1' == 'I am p2' ?
Returning FALSE from the client-defined reporting function.
Inside the client-defined reporting function.
This is the number of Assertion failures that have occurred: 1
Returning TRUE from the client-defined reporting function.
dbgmacro.c(55) : Assertion failed
Inside the client-defined reporting function.
This is the debug user message: dbgmacro.c(57) : Will _ASSERTE find 'I am p1' == 'I am p2' ?
Returning FALSE from the client-defined reporting function.
Inside the client-defined reporting function.
This is the number of Assertion failures that have occurred: 2
Returning TRUE from the client-defined reporting function.
dbgmacro.c(58) : Assertion failed: p1 == p2
Inside the client-defined reporting function.
This is the debug user message: 'I am p1' != 'I am p2'
Returning FALSE from the client-defined reporting function.