【MSVC】_invalid_parameter和_invoke_watson

最近遇到一个崩溃问题,崩溃在CRT中,最后调用的函数是_invoke_watson。调用关系大概如下:

_invoke_watson
_invalid_parameter
_invalid_parameter_noinfo_noreturn
memcpy_s

虽然看的出来这个是memcpy参数不对导致的崩溃,但是这几个之前没见过的函数成功吸引了我的注意!

这一系列的函数用在windows CRT中处理函数的无效传参。_invalid_parameter的函数原型如下:

extern "C" void __cdecl
_invalid_parameter(
    wchar_t const* const expression,
    wchar_t const* const function_name,
    wchar_t const* const file_name,
    unsigned int   const line_number,
    uintptr_t      const reserved);

它会调用处理函数(默认为_invoke_watson),比如结束程序等。_invalid_parameter_noinfo_noreturn和_invoke_watson不会返回调用者函数。

CRT支持设置自定义像_invoke_watson这样的处理函数,_set_invalid_parameter_handler为全局的,_set_thread_local_invalid_parameter_handler只是针对当前线程的:

_invalid_parameter_handler _set_invalid_parameter_handler(
   _invalid_parameter_handler pNew
);
_invalid_parameter_handler _set_thread_local_invalid_parameter_handler(
   _invalid_parameter_handler pNew
);
_invalid_parameter_handler _get_invalid_parameter_handler(void);
_invalid_parameter_handler _get_thread_local_invalid_parameter_handler(void);

自定义的处理函数原型如下:

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

一个例子:

#include <iostream>
#include <stdlib.h>
using namespace std;

void globalInvalidParameterHandler(const wchar_t* expression,
								   const wchar_t* function,
								   const wchar_t* file,
								   unsigned int line,
								   uintptr_t pReserved) {
	printf("invalid param!\n");
	abort();
}

void handleA(int size) {
	if(size <= 0) {
		_invalid_parameter_noinfo();
	}
}

int main(int argc, char* argv[]) {
	_invalid_parameter_handler oldHandler;
	oldHandler = _set_invalid_parameter_handler(globalInvalidParameterHandler);

	handleA(0);

	return 0;
}
posted @ 2019-03-16 01:20  tkorays  阅读(1111)  评论(0编辑  收藏  举报