zoukankan      html  css  js  c++  java
  • 错误处理

    今天就来了解下windows下的函数是如何进行错误处理的。

    调用函数时,它会先验证我们传入的参数,再执行任务。下面是常见的windows函数返回值数据类型。

    Microsoft为我们编辑了一个列表,其中列出了各种错误代码及其对应的32位的编号,方便我们理解函数为什么会调用失败。

    在内部,当windows函数检测到错误时,它会使用“线程本地存储区”(thread-local storage)将相应的错误代码与“主调线程”绑定到一起。它使得不同线程独立运行,并不会干扰对方的错误代码的情况。函数返回值会指出已发生一个错误。要想查看具体的错误,需要调用GetLastError函数。eg:

    DWORD GetLastError();

    其作用就一个,即返回由上一个函数调用设置的线程的32位错误代码。

    这还不够,我们还需要将其转化为更有用的信息。WinError.h文件里包含了Microsoft定义的错误代码列表。如:

    可以看到,每个错误都有三种表示:一个消息ID(可以在源代码中使用的宏,用于与GetLastError的返回值进行比较)、消息文本和一个编号。

    一些windows函数调用成功可能源于不同的原因,而应用程序或许需要知道成功的原因。为返回这种信息,Microsoft选择采用last error code机制。即可以用GetLastError来确定额外信息。所以,GetLastError的返回值可以表示错误信息,也可以表示成功信息,这要看对应的消息ID了。

    当我们调试程序时,对线程的GetLastError进行监视是很有必要的。在VS中,Microsoft的调试器提供watch窗口,可以帮助我们。具体的做法是:在watch窗口中选择一行,输入$err,hr。来看个例子,下图。我已经调用了CreateFile函数,其返回值为INVALID_HANDLE_VALUE(-1)的一个HANDLE,指出无法打开文件。但是,watch窗口指出,GetLastError的返回值为0x00000002。多亏了,hr限定符,watch窗口进一步指出错误代码2是“The system cannot find the file specified."这就是消息文本。

    VS还搭载了一个很小的实用程序,名为Error Lookup。利用它,可以将消息ID转化为消息文本。如:

    如果我希望程序向用户显示错误文本,而不是一个苦逼的ID,那么可以利用这个函数FormatMessage:

    DWORD FormatMessage(
        DWORD dwFlags,
        LPCVOID pSource,
        DWORD dwMessageId,
        DWORD dwLanguageId,
        PTSTR pszBuffer,
        DWORD nSize,
        va_list *Arguments);

    其功能很不错,可以支持多种语言,从其参数dwLanguageId就可以看出来。其用法后面有示例。

    定义自己的错误代码

    在我们自定义的函数里,我们可以为其自行设置错误代码。为了指出错误,我们只需设置线程的上一个错误代码,然后令自己的函数返回FALSE或其他合适的值。为了设置线程的上一个错误代码,只需调用SetLastError函数,并传递我们认为合适的任何32位值。

    VOID SetLastError(DWORD dwErrCode);

    我会尽量使用WinError.h中现有的代码。也可自己创建自己的代码。错误代码是一个32位数,由下表字段组成。

    就目前来说,我们只需要注意一个字段---第29位。注意:Facility字段很大,足以容纳4096个可能的值。其中,前256个值为Microsoft保留的,其余值我们随意设定。

    ErrorShow示例程序

    这个应用程序演示了如何得到一个错误代码的文本描述。简单来说,它展示了调试器的watch窗口和Error Lookup程序是如何工作的。启动程序时,将出现下面窗口:

    输入错误代码ID,单击Lookup按钮,即可以看到消息文本。下面截取其源代码中FormatMessage的调用部分:

    上述代码中,第一行从编辑控件获取错误代码。然后,指向一个内存块的句柄被实例化并初始化为NULL。FormatMessage函数在内部分配一块内存,并返回指向该内存的句柄。调用FormatMessage时,我向它传入了FORMAT_MESSAGE_FROM_SYSTEM标志。该标志告诉FormatMessage:我们希望获得与一个系统定义的错误代码对应的字符串。另外,还传入了FORMAT_MESSAGE_ALLOCATE_BUFFER标志,要求该函数分配一块足以容纳错误文本描述的内存。此块内存的句柄将在hlocal变量中返回。FORMAT_MESSAGE_IGNORE_INSERTS标志则允许我们获得含有%占位符的消息,这些占位符将被windows用来提供更多上下文相关信息。第三个参数指出想要查找的错误代码,第四个参数指出语言选择。由于我们对windows本身所提供的信息感兴趣,所以将根据两个特定的常量(即LANG_NEUTRAL和SUBLANG_NEUTRAL)来生成语言标识符,这两个常量联合到一起将生成一个0值--即操作系统默认语言。

    我们可以向自己的模块中添加错误代码,具体做法是使用Message Compiler(MC.exe)来创建一个消息资源并将其添加到DLL或exe模块中。VS的Error Lookup工具允许我们使用Modules对话框来完成这个操作。

  • 相关阅读:
    poj 2676 Suduku (dfs)
    poj 1562 Oil Deposits (dfs)
    poj 2907 Collecting Beepers (dfs)
    poj 1655 Balancing Act (树形dfs)
    poj 3411 Paid Roads (dfs)
    hdu 2896 病毒侵袭 (AC)
    hdu 3065 病毒侵袭持续中 (AC)
    poj 2251 Dungeon Master (bfs)
    java中debug使用
    Swing入门级小项目总结
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4677214.html
Copyright © 2011-2022 走看看