_CrtDbgReport

Generates a report with a debugging message and sends the report to three possible destinations (debug version only).

int _CrtDbgReport( int reportType, const char *filename, int linenumber, const char *moduleName, const char *format [, argument] ... );

Routine Required Header Compatibility
_CrtDbgReport <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

For all report destinations, _CrtDbgReport returns –1 if an error occurs and 0 if no errors are encountered. However, when the report destination is a debug message window and the user chooses the Retry button, _CrtDbgReport returns 1. If the user chooses the Abort button in the debug message window, _CrtDbgReport immediately aborts and does not return a value.

The _ASSERT[E] and _RPT, _RPTF debug macros call _CrtDbgReport to generate their debug report. When _CrtDbgReport returns 1, these macros start the debugger, provided that “just-in-time” (JIT) debugging is enabled.

Parameters

reportType

Report type: _CRT_WARN, _CRT_ERROR, _CRT_ASSERT

filename

Pointer to name of source file where assert/report occurred or NULL

linenumber

Line number in source file where assert/report occured or NULL

moduleName

Pointer to name of module (.EXE or .DLL) where assert/report occurred

format

Pointer to format-control string used to create the user message

argument

Optional substitution arguments used by format

Remarks

The _CrtDbgReport function is similar to the printf function, as it can be used to report warnings, errors, and assert information to the user during the debugging process. However, this function is more flexible than printf because it does not need to be enclosed in #ifdef statements to prevent it from being called in a retail build of an application. This is achieved by using the _DEBUG flag: When _DEBUG is not defined, calls to _CrtDbgReport are removed during preprocessing.

_CrtDbgReport can send the debug report to three different destinations: a debug report file, a debug monitor (the Visual C++ debugger), or a debug message window. Two configuration functions, _CrtSetReportMode and _CrtSetReportFile, are used to specify the destination(s) for each report type. These functions allow the reporting destination(s) for each report type to be separately controlled. For example, it is possible to specify that a reportType of _CRT_WARN only be sent to the debug monitor, while a reportType of _CRT_ASSERT be sent to a debug message window and a user-defined report file.

_CrtDbgReport creates the user message for the debug report by substituting the argument[n] arguments into the format string, using the same rules defined by the printf function. _CrtDbgReport then generates the debug report and determines the destination(s), based on the current report modes and file defined for reportType. When the report is sent to a debug message window, the filename, lineNumber, and moduleName are included in the information displayed in the window.

The following table lists the available choices for the report mode(s) and file and the resulting behavior of _CrtDbgReport. These options are defined as bit-flags in CRTDBG.H.

Report Mode Report File _CrtDbgReport Behavior
_CRTDBG_-
MODE_DEBUG
Not applicable Writes message to Windows OutputDebugString API.
_CRTDBG_-
MODE_WNDW
Not applicable Calls Windows MessageBox API to create message box to display the message along with Abort, Retry, and Ignore buttons. If user selects Abort, _CrtDbgReport immediately aborts. If user selects Retry, it returns 1. If user selects Ignore, execution continues and _CrtDbgReport returns 0. Note that choosing Ignore when an error condition exists often results in “undefined behavior.”
_CRTDBG_-
MODE_FILE
__HFILE Writes message to user-supplied HANDLE, using the Windows WriteFile API, and does not verify validity of file handle; the application is responsible for opening the report file and passing a valid file handle.
_CRTDBG_-
MODE_FILE
_CRTDBG_-
FILE_STDERR
Writes message to stderr.
_CRTDBG_-
MODE_FILE
_CRTDBG_-
FILE_STDOUT
Writes message to stdout.

The report may be sent to one, two, or three destinations, or no destination at all. For more information about specifying the report mode(s) and report file, see the _CrtSetReportMode and _CrtSetReportFile functions. For more information about using the debug macros and reporting functions, see Using Macros for Verification and Reporting and Debug Reporting Functions of the C Run-Time Library.

If your application needs more flexibility than that provided by _CrtDbgReport, you can write your own reporting function and hook it into the C run-time library reporting mechanism by using the _CrtSetReportHook function.

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 FALSE 0
#define TRUE !FALSE

/* 
 * 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(stdout, "Inside the client-defined reporting function.\n");
   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(stdout, "This is the number of Assertion failures that have occurred: %d \n", gl_num_asserts);
      fflush(stdout);
      fprintf(stdout, "Returning TRUE from the client-defined reporting function.\n");
      fflush(stdout);
      return(TRUE);
   } else {
      fprintf(stdout, "This is the debug user message: %s \n", userMessage);
      fflush(stdout);
      fprintf(stdout, "Returning FALSE from the client-defined reporting function.\n");
      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.

Debug Functions

See Also   _CrtSetReportMode, _CrtSetReportFile, printf, _DEBUG