In VC8/9, many CRT functions check the legality of incoming arguments. When a CRT function detects an illegal parameter passed in, it invokes an illegal parameter-handling routine. The default illegal parameter handling routine is to call Watson Crash Reporting, crash the application, and ask the user if they want to send crash data dumps to Microsoft Analytics. In debug mode, illegal arguments also produce failed assertions.
You can set custom processing routines by calling _set_invalid_parameter_handler instead of the default processing routines. If you specify a processing routine that does not terminate the program, the CTR function will regain control after the processing routine returns. At this point, these CTR functions usually stop executing, return an error code, and set the errno. In most cases, both the errno value and the return value are einval, indicating an illegal parameter. In some cases, a more detailed error code is returned.
The _set_invalid_parameter_handler function prototype is as follows:
_invalid_parameter_handler _set_invalid_parameter_handler(
_invalid_parameter_handler pNew
);
It replaces the existing processing routines with the processing routines specified by the parameter pnew and returns the substituted processing routines.
The function prototype of the illegal parameter handling routine type _invalid_parameter_handler is as follows:
void _invalid_parameter(
const wchar_t * expression,
const wchar_t * function,
const wchar_t * file,
unsigned int line,
uintptr_t pReserved
);
Where the first parameter is a parameter expression, the second parameter is the name of the CRT function that found the illegal parameter, the third parameter is the file name of the CRT source code, the fourth parameter is the line of code, and the last parameter is a reserved value. If you are using a non-debug version of the CRT library, all of these parameter values are null.
Refer to the examples on MSDN as follows:
// crt_set_invalid_parameter_handler.c
// compile with: /Zi /MTd
#include <stdio.h>
#include <stdlib.h>
#include <crtdbg.h> // For _CrtSetReportMode
void myInvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
wprintf(L"Invalid parameter detected in function %s."
L" File: %s Line: %d\n", function, file, line);
wprintf(L"Expression: %s\n", expression);
}
int main( )
{
char* formatString;
_invalid_parameter_handler oldHandler, newHandler;
newHandler = myInvalidParameterHandler;
oldHandler = _set_invalid_parameter_handler(newHandler);
// Disable the message box for assertions.
_CrtSetReportMode(_CRT_ASSERT, 0);
// Call printf_s with invalid parameters.
formatString = NULL;
printf(formatString);
}
Run results (VC9 SP1):
Invalid parameter detected in function printf. FILE:F:\DD\VCTOOLS\CRT_BLD\SELF_X86\CRT\SRC\PRINTF.C line:54expression: (Format!= NULL)
One point about this example is that _CrtSetReportMode (_crt_assert, 0) is invoked to turn off the ASSERT report of the debug version of the CRT function on illegal arguments. In fact, the opening and closing of some other features in the CRT library will need to be turned off in the debug edition to be able to manifest. For example, if you want to throw an exception when the checked iterator crosses over, you can define a macro _secure_scl_throws value of 1. However, if the debug edition does not turn off assert, the CRT will use the Assert report to cross the line before the exception is thrown, which hides the thrown exception (of course, if you choose ignore in the Assertion Failure dialog box that pops up, you can catch the exception).