VC8/9中CRT函数对非法参数的处理

在VC8/9中,许多CRT函数会检查传入的参数的合法性。当CRT函数检测到一个非法参数传入时,它会调用“非法参数处理例程”。默认的非法参数处理例程是调用Watson Crash Reporting,让应用程序崩溃,并询问用户是否愿意发送崩溃数据转储给Microsoft分析。在Debug模式下,非法参数还会产生失败的断言。

可以通过调用_set_invalid_parameter_handler来设置自定义处理例程,来代替默认的处理例程。如果你指定的处理例程没有终止程序,那么在该处理例程返回后,该CTR函数将重新获得控制权。此时,这些CTR函数通常停止执行,并返回一个错误代码,并设置errno。多数情况下,errno值和返回值都是EINVAL,指示一个非法参数。某些情况下,会返回一个更详细的错误代码。

_set_invalid_parameter_handler函数原型如下:

_invalid_parameter_handler _set_invalid_parameter_handler(
_invalid_parameter_handler pNew
);

它使用参数pNew指定的处理例程代替现有处理例程,并返回被代替的处理例程。

非法参数处理例程类型_invalid_parameter_handler的函数原型如下:

void _invalid_parameter(
const wchar_t * expression,
const wchar_t * function,
const wchar_t * file,
unsigned int line,
uintptr_t pReserved
);

其中,第一个参数是参数表达式,第二个参数是发现非法参数的CRT函数名,第三个参数是CRT源代码的文件名,第四个参数是代码行,最后一个参数为保留值。如果使用非Debug版CRT库,则所有这些参数值都为NULL。

引用MSDN上的例子如下:

// 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);
}

运行结果(VC9 SP1):

Invalid parameter detected in function printf. File: f:\dd\vctools\crt_bld\self_x86\crt\src\printf.c Line: 54Expression: (format != NULL)

关于此例子的一点说明:例子中调用了_CrtSetReportMode(_CRT_ASSERT, 0)来关闭Debug版CRT函数对非法参数的ASSERT报告。事实上,CRT库中其它一些特性的开启与关闭在Debug版下都需要关闭ASSERT报告才能够体现。例如,如果要使Checked Iterator越界发生时抛出异常,则可以定义宏_SECURE_SCL_THROWS的值为1。然而,如果Debug版不关闭ASSERT,则会在抛出异常之前CRT先使用ASSERT报告越界,这就隐藏了抛出的异常(当然,如果你在弹出的断言失败对话框中选择“忽略”后,还是能够捕获到异常的)。

时间: 2024-10-24 17:13:43

VC8/9中CRT函数对非法参数的处理的相关文章

helper_string.h中checkCmdLineFlag函数功能以及参数含义

问题描述 helper_string.h中checkCmdLineFlag函数功能以及参数含义 vs中cuda编程时,代码中碰到checkCmdLineFlag(argc, (const char **)argv, "help"),不知道含义,请各位大侠解答. 解决方案 参数就是三个参数,arge和argv代表参数个数和一个带有命令行字符串的二级指针,第三个参数是你要找的字符串(比如"help","device") inline bool che

php中preg_match过滤URL非法参数程序

PHP开发中经常用到URL传递参数,对传递的参数要进行安全过滤,过滤URL中非法参数,这是php安全的一个细小的地方,却事关安全的大事.URL参数一般都是数字或者字母加上"-"或者"_"组成,参数带有其他的符号的都要进行过滤,以免带来安全问题.对URL传参进行非法字符过滤,用preg_match很容易判断非法的参数.  代码如下 复制代码 if(!preg_match("/^[a-z0-9_\-]+$/i",$this->commentid

详解C++编程中向函数传递引用参数的用法_C 语言

引用类型的函数参数向函数传递引用而非大型对象的效率通常更高. 这使编译器能够在保持已用于访问对象的语法的同时传递对象的地址. 请考虑以下使用了 Date 结构的示例: // reference_type_function_arguments.cpp struct Date { short DayOfWeek; short Month; short Day; short Year; }; // Create a Julian date of the form DDDYYYY // from a G

JS中定义函数时的参数定义为undefined

问题描述 看到大牛们写的js源码,想拜读学习一下.var KISSY = (function (undefined) { var host = this, S, guid = 0, EMPTY = ''; S = { __BUILD_TIME: '20130701201313', ... }; // exports for nodejs if (S.Env.nodejs) { S.KISSY = S; module.exports = S; } return S;})();请看以上的代码,为什么

C++中成员函数(member function)模板(template) 详解

成员模板(member template) 既可以在普通类(ordinary class), 也可以在类模板(class template); 在普通类中, 在使用成员函数时, 不用提供模板参数, 函数可以根据使用的参数, 自动推导(deduce)模板实参(template argument)对应模板形参(template parameter); 在类模板中, 成员函数的模板参数(template parameter)可以和类的模板参数不同, 但在定义(definition)中, 必须添加两个模

SQL中函数 replace 的参数1的数据类型ntext无效的解决方法

今天将一个ACC的数据库转换成ms-sql以后发现在使用replace替换语句的时候出现: SQL中函数 replace 的参数 1 的数据类型 ntext 无效.找了半天找到了解决办法: 因为ntext需要转化下 用如下语句即可解决: 复制代码 代码如下:UPDATE 表 SET 字段=REPLACE(cast(字段 AS varchar(8000)),'被替换的内容','将要替换成的内容') varchar(8000)是字段类型.8000是个很猛的字段,可以根据自己的实际情况改动!

Swift 3 中的函数参数命名规范指北

本文讲的是Swift 3 中的函数参数命名规范指北, 昨天,我开始将这个 Jayme 迁移到 Swift 3.这是我第一次将一个项目从 Swift 2.2 迁移至 Swift 3.说实话这个过程十分的繁琐,由于 Swift 3 在老版本基础上发生了很多比较大的改变,我不得不承认眼前这样一个事实,除了花费较多的时间以外,没有其余的捷径可走.不过这样的经历也带来一点好处:我对 Swift 3 的理解变得更为深入,对我来讲,这可能是最好的消息了. 在迁移代码的过程中,我需要做出很多的选择.更为蛋疼的是

linux驱动-Linux驱动结构体中probe函数的参数怎么得到?

问题描述 Linux驱动结构体中probe函数的参数怎么得到? 解决方案 他既然都写了那在驱动文件里面应该会有这个函数啊,这种敦泰的TP驱动在SDK里面能找到好几个吧 解决方案二: static int ft5x_ts_probe(struct i2c_client *client const struct i2c_device_id *id) 函数原型是这个,我疑问的是原函数的这两个参数怎么确定的?{...

关于c++的中函数指针作为参数的问题

问题描述 关于c++的中函数指针作为参数的问题 函数实现 void swap(int &a, int &b) { int tmp = a; a = b; b = tmp; } 函数使用: int i=1,j=2: swap(i,j): 如上所示,swap函数传递进来的是两个整形变量的地址,有两个问题 1.那么swap的实现里面,为什么直接交换a,b的值就实现了地址交换?难道这里的a,b代表指针吗? 2.使用swap时为什么没有使用swap(&i,&j)? 初学c++,还望大