Windows下的api 以及 C语言的一些api

目录

iswpunct()——判断一个宽字符是不是标点符号

RegisterClass 宏  

DefWindowProc 宏

 IsIconic 函数

HWND和HDC和HINSTANCE

PathFileExists——不精确判断文件和目录是否存在的

CreateFile——以何种模式创建文件

EXCEPTION_POINTERS 异常结构体

_set_se_translator 函数——把SEH异常转换成C++异常

GetExceptionInformation 宏——获取异常信息

SetUnhandledExceptionFilter 函数——设置一个回调函数,用来设置对于未经处理的异常的处理函数

结构化异常 和 标准C++异常

C++语言的异常

windows平台的异常:

        生成dump


 

windows下的,参考文档msdn

c语言标准库中的,https://en.cppreference.com

 

iswpunct()——判断一个宽字符是不是标点符号

 <cwctype>

https://en.cppreference.com/w/cpp/string/wide/iswpunct

 

 

 

RegisterClass 宏  

winuser.h 

#ifdef UNICODE
#define RegisterClass  RegisterClassW
#else
#define RegisterClass  RegisterClassA
#endif // !UNICODE

https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-registerclassw

注册一个窗口类,在随后的CreateWindow 或者 CreateWindowEx 中调用。(Registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function.)

(Note  The RegisterClass function has been superseded by the RegisterClassEx function. You can still use RegisterClass, however, if you do not need to set the class small icon.

set the class small icon 这个什么玩意 )
 

    WNDCLASS    wc;                        // Windows Class Structure
    memset(&wc, 0, sizeof(WNDCLASS));
    // 设置一堆值
    wc.style            =
    wc.lpfnWndProc        =
    wc.cbClsExtra        =
    wc.cbWndExtra        =
    wc.hInstance        =
    wc.hIcon            =
    wc.hCursor            =
    wc.hbrBackground    =
    wc.lpszMenuName        =
    wc.lpszClassName    =

    if (!RegisterClass(&wc))                                    // Attempt To Register The Window Class
    {
        return false;                                            // Return FALSE
    }
    //.....中间一堆值的设置以后 调用CreateWindow
    // Create The Window
    HWND _hWnd=CreateWindow(		L"OpenGL",							  // Class Name
							title,									// Window Title
							dwStyle,
							window_x, window_y,					// Window Position
							width,	// Calculate Window Width
							height,	// Calculate Window Height
							NULL,								// No Parent Window
							NULL,								// No Menu
							_hInstance,						// Instance
							NULL);							   // Dont Pass Anything To WM_CREATE
	if(_hWnd == NULL)
	{
		return false;
	}

重要变量:wc.lpfnWndProc 

这个RegisterClass是为了可以创建自己的窗口类,虽然windows也有很多预设的窗口类。

 

DefWindowProc 宏

#ifdef UNICODE
#define DefWindowProc  DefWindowProcW
#else
#define DefWindowProc  DefWindowProcA
#endif // !UNICODE

https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-defwindowproca

调用默认的窗口过程处理函数。一般都是自定义的一个窗口过程处理函数,最后没有处理的再调用这个。窗口过程处理函数在 窗口类 的一个成员变量中设置  wc.lpfnWndProc

(Calls the default window procedure to provide default processing for any window messages that an application does not process. This function ensures that every message is processed. DefWindowProc is called with the same parameters received by the window procedure.)

 IsIconic 函数

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isiconic

窗口是不是最小化(Determines whether the specified window is minimized (iconic).)

BOOL IsIconic( HWND hWnd );

 

HWND和HDC和HINSTANCE

HWND和HDC都是句柄,不过前者是HWND是窗口句柄,HDC是设备描述表的句柄。

hWnd(Handle of Window,也可以这么说:h是类型描述,表示句柄;wnd是变量对象描述,表示窗口)是窗口句柄,其中包含窗口的属性。例如,窗口的大小、显示位置、父窗口。

hDC(Handle to Device Context)是图像的设备描述表,窗口显示上下文句柄,其中可以进行图形显示。

利用hDC=GetDC(hWnd),可以获得一个窗口的图形设备描述表。可以通过ReleaseDC()函数释放。

 

hWnd句柄是描述一个窗口的形状、位置、大小、是否显示、它的父窗口、兄弟窗口、等等的一组数据结构;  
hDC句柄是一个实实在在的用于具体表现这个窗口时,需要对这个窗口有个场合来实现的地方。

 

hWnd是窗体句柄;hDC是设备场景句柄。
hWnd与窗口管理有关;hDC与绘图API(GDI函数)有关。
hWnd是windows给窗口发送消息(事件)用的;hDC是把窗口绘制在屏幕上用的。
有了hWnd,可以使用API的GetDC()函数得到与其相关的hDC:hDC=GetDC(hWnd)。

PathFileExists——不精确判断文件和目录是否存在的

      access()                     (C ,  Windows and Linux)

      PathFileExists()         (Windows API ,  Windows)——https://docs.microsoft.com/zh-cn/windows/win32/api/shlwapi/nf-shlwapi-pathfileexistsa

 

CreateFile——以何种模式创建文件

CreateFile 函数创建或打开下列对象,并返回一个可以用来访问这些对象的句柄。 
  文件 
 pipes
  邮槽 
  通信资源 
  磁盘驱动器(仅适用于 windowsNT ) 
  控制台 
  文件夹(仅用于打开)

HANDLE CreateFile(
 LPCTSTR lpFileName,    // 指向文件名的指针 
 DWORD dwDesiredAccess,    // 访问模式(写 / 读) 
 DWORD dwShareMode,    // 共享模式 
 LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 指向安全属性的指针 
 DWORD dwCreationDisposition,   // 如何创建 
 DWORD dwFlagsAndAttributes,   // 文件属性 
 HANDLE hTemplateFile    // 用于复制文件句柄 
);

https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea

 

DWORD dwCreationDisposition,   // 如何创建 值常用有:——获取上一个错误 用GetLastError() 函数

Windows下的api 以及 C语言的一些api

 

EXCEPTION_POINTERS 异常结构体

typedef struct _EXCEPTION_POINTERS {
  PEXCEPTION_RECORD ExceptionRecord;
  PCONTEXT          ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_pointers

an exception record with a machine-independent description of an exception and  异常记录信息,机器无关。

a context record with a machine-dependent description of the processor context at the time of the exception. 上下文记录,异常发生时的处理器的上下文,机器有关

 

 

_set_se_translator 函数——把SEH异常转换成C++异常

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/set-se-translator?view=msvc-160

 

函数定义:

_se_translator_function _set_se_translator(
    _se_translator_function seTransFunction
);

 

其中seTransFuncion的类型签名:

typedef void (*_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS* );

第一个参数是int,通过GetExceptionCode 宏获取的,具体参见https://docs.microsoft.com/en-us/windows/win32/debug/getexceptioncode,有哪些返回值。

第二个参数是EXCEPTION_POINTERS的指针,通过GetExceptionInformation 宏获得的,这个宏 具体看下面有介绍。

函数的实现体一般都是把throw一个异常类一般是这么实现的:

/************************************************************************/
/* 自定义异常类 主要是转换结构化异常到标准c++异常 易于捕获  
/************************************************************************/
#ifndef __ExceptionTransfer_H__
#define __ExceptionTransfer_H__
#include "stdafx.h"
class MyException
{
public:
 MyException(unsigned int code,_EXCEPTION_POINTERS * ptr):errcode(code),ptreception(ptr){}
 unsigned int errcode;
 _EXCEPTION_POINTERS *ptreception;
};
#endif

 

 _set_se_translator这个函数只对当前线程有用,其它线程要想转换SEH的异常就必须调用_set_se_translator一次。

这个函数的目的就是把SEH异常转换成C++异常。设置seTransFuntion实现体中跑出一个C++异常,seTransFuntion的函数签名的输入参数一个是GetExceptionCode 获取,一个是GetExceptionInformation 获得(在处理函数里面抛出一个标准的C++异常(比如throw 1),这样try catch就可以捕获到了)

除了 _set_se_translator 之外,还有两外几个类似的函数,

 _set_invalid_parameter_handler(throw_InValidParmerHandel); //捕获无效参数错误 ex:atoi(NULL)
 _set_purecall_handler(throw_PureCallHandel); //捕获虚函数调用错误
 ::_set_new_handler(throw_Mybadlloc);
 ::_set_new_mode(1);

void throw_InValidParmerHandel(const wchar_t * express, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t p_ress)
{
 throw 234;
}

void throw_PureCallHandel(void)
{
 throw 123;
}

int throw_Mybadlloc( size_t requireSize )
{
 g_FatalLog.WriteStr( "分配内存失败");
 abort();
 return EXCEPTION_EXECUTE_HANDLER;
}

 

GetExceptionInformation 宏——获取异常信息

https://docs.microsoft.com/en-us/windows/win32/debug/getexceptioninformation

#define GetExceptionInformation     (struct _EXCEPTION_POINTERS *)_exception_info

只能用在特定的地方,异常处理里面,用在其他地方会编译出错,C++将这个当作是关键字

__try 
{ 
     // try block 
} 
__except ( FilterFunction(GetExceptionInformation() ) //FilterFunction函数自己定义的
{ 
    // exception handler block 
}


 //FilterFunction函数自己定义的
bool FilterFunction(PEXCEPTION_POINTERS pException)
{
    // 处理函数 通过对 pException的两个成员 ExceptionRecord 和  ContextRecord 记录一些可读信息 略
}

SetUnhandledExceptionFilter 函数——设置一个回调函数,用来设置对于未经处理的异常的处理函数

https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setunhandledexceptionfilter

LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter( LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter );

输入参数:LPTOP_LEVEL_EXCEPTION_FILTER 是设置的回调函数的签名类型,具体是:

LONG UnhandledExceptionFilter(
  _EXCEPTION_POINTERS *ExceptionInfo
);

返回参数:也是LPTOP_LEVEL_EXCEPTION_FILTER ,那么代表的是上一次通过SetUnhandledExceptionFilter设置的回调函数的地址:The SetUnhandledExceptionFilter function returns the address of the previous exception filter established with the function. A NULL return value means that there is no current top-level exception handler.

当发生异常时,比如内存访问违规时,CPU硬件会发现此问题,并产生一个异常(你可以把它理解为中断),

然后CPU会把代码流程切换到异常处理服务例程。

操作系统异常处理服务例程会查看当前进程是否处于调试状态,如果是则通知调试器发生了异常,

如果不是则操作系统会查看当前线程是否安装了异常帧链(FS[0]),如果安装了SEH,则调用SEH,并根据返回结果决定是否全局展开或局部展开。

如果异常链中所有的SEH都没有处理此异常,而且此进程还处于调试状态,则操作系统会再次通知调试器发生异常(二次异常)。

如果还没人处理,则调用操作系统的默认异常处理代码UnhandledExceptionHandler,不过操作系统允许你Hook这个函数,就是通过SetUnhandledExceptionFilter函数来设置。

大部分异常通过此种方法都能捕获,不过栈溢出、覆盖的有可能捕获不到。

 

其中UnhandledExceptionFilter的返回值是long类型,其值具体有

EXCEPTION_CONTINUE_EXECUTION (–1) 异常被忽略,控制流将在异常出现的点之后,继续恢复运行。

EXCEPTION_CONTINUE_SEARCH (0) 异常不被识别,也即当前的这个__except模块不是这个异常错误所对应的正确的异常处理模块。系统将继续到上一层的try-except域中继续查找一个恰当的__except模块。

EXCEPTION_EXECUTE_HANDLER (1) 异常已经被识别,也即当前的这个异常错误,系统已经找到了并能够确认,这个__except模块就是正确的异常处理模块。控制流将进入到__except模块中。  

 

对于异常的一点认识

结构化异常 和 标准C++异常

结构化异常 也叫“SEH异常” windows下: 的__try...__except(1)

标准C++异常: try{}catch(...){}

一个函数中不能既有 标准C++异常 也有 结构化异常的写法。那都想支持怎么办,如下配置一下:

Windows下的api 以及 C语言的一些api

这样的话使用C++异常也能够捕获到SEH异常”。这样无论是在EXE还是DLL中,try{}catch(...){}同样可以捕获Windows异常

那么什么是C++语言的异常,什么Windows平台的异常呢?

C++语言的异常

https://www.runoob.com/cplusplus/cpp-exceptions-handling.html

是用于处理语言本身的一些问题,如指针为空、如除数为0,之类的。这没什么多说的。

语法是:

try 
{  
    包含可能抛出异常的语句;  
}  
catch(类型名& 实例名)    // 可以是特定的异常实例  
{  
  
}  
catch(类型名)    // 也可以只是特定类型
{  
  
}  
catch(...)    // 三个点则表示捕获所有类型的异常  
{ 
}  

Windows下的api 以及 C语言的一些api

Windows下的api 以及 C语言的一些api

如果一般会自定义一个类,继承自std::exception

#include <iostream>
#include <exception>
using namespace std;
 
struct MyException : public exception
{
  const char * what () const throw ()
  {
    return "C++ Exception";
  }
};
 
int main()
{
  try
  {
    throw MyException();
  }
  catch(MyException& e)
  {
    std::cout << "MyException caught" << std::endl;
    std::cout << e.what() << std::endl;
  }
  catch(std::exception& e)
  {
    //其他的错误
  }
}

windows平台的异常:

比如在用VS开发时,有时会碰到“未处理的异常”,然后弹出一个框,代码停在出错的地方。类似于内存访问越界之类的。

 

生成dump

//创建DBGHLEP所需要的dmp信息
BOOL CreateDumpHelpFile(PEXCEPTION_POINTERS pException, PTCHAR szDumpFile)
{
 MINIDUMP_EXCEPTION_INFORMATION M;
 M.ThreadId = GetCurrentThreadId();
 M.ExceptionPointers = pException;
 M.ClientPointers = 0;
 HANDLE hDump_File = CreateFile(szDumpFile,
  GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
 if (hDump_File == INVALID_HANDLE_VALUE)
 {
  if (GetLastError() == ERROR_FILE_EXISTS)
  {
  }
  else
  {
  }
 }
 else
 {
  MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDump_File,
   MiniDumpNormal, (pException) ? &M : NULL, NULL, NULL);
  CloseHandle(hDump_File);

 }
 return TRUE;
}

 

上一篇:Hive


下一篇:Spark Java版本wordCount