browser icon
You are using an insecure version of your web browser. Please update your browser!
Using an outdated browser makes your computer unsafe. For a safer, faster, more enjoyable user experience, please update your browser today or try a newer browser.

杂谈Win32中的“最近错误代码”

Posted by on 2008 年 08 月 26 日

你可以任意转载本文,但请在转载后的文章中注明作者和原始链接。
媒体约稿请联系 titilima_AT_163.com(把“_AT_”换成“@”)。

Windows 系统为每一个线程维护了一个“最近错误代码”(Last Error Code),这个代码记录了当 API 函数调用失败时相对详细的错误原因。通常,使用 Win32 API 的 GetLastError 可以获得这个代码: 

C++代码
  1. DWORD GetLastError(void);  

在获取了错误代码之后,辅以 FormatMessage 函数就可以得到这个错误代码所表示的详细文字说明。
在 Visual Studio 的调试环境下,可以在Watch视图中输入“@err,hr”来实时监视这个代码,如下图:

在 WinDbg 的调试环境下,则可以使用 !gle 命令来查看相关的信息。
需要注意的一点是,这个代码是“最近的”错误代码。换句话说,它只保留上一次调用失败的代码,而对于成功执行的 API 函数而言,是并不会更新这个值的。考虑如下代码:

C++代码
  1. #include <Windows.h>   
  2. #include <stdio.h>   
  3. #include <tchar.h>   
  4.   
  5. int main(void)   
  6. {   
  7.     HANDLE hFile = CreateFile(_T("C:\\1.txt"), GENERIC_WRITE, 0, NULL,   
  8.         CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);   
  9.     printf("Error Code 1: %d.", GetLastError());   
  10.   
  11.     DeleteFile(_T("C:\\1.txt"));   
  12.     printf("Error Code 2: %d.", GetLastError());   
  13.   
  14.     CloseHandle(hFile);   
  15.     DeleteFile(_T("C:\\1.txt"));   
  16.     printf("Error Code 3: %d.", GetLastError());   
  17.     return 0;   
  18. }  

CreateFile 是一个成功的操作,所以 GetLastError 的值是 0 。由于 CreateFile 独占打开 1.txt ,所以接下来的 DeleteFile 会失败,GetLastError 返回 32 。CloseHandle 之后,虽然 DeleteFile 成功执行,但 GetLastError 仍然会返回 32 。

订阅本站

4 Comments

  • At 2008.08.27 10:00, sPhinX said:

    这个好像不算杂谈吧,只是GetLastError的基本含义,原本以为能看到难得的经验的,记得以前COM集中营里有一篇Debug的文章,说是一个很奇怪的Bug就是由GetLastError改变了现场数据导致的,那还有点意思。

    • At 2008.09.06 14:50, sPhinX said:

      COM集中营已经没了,今天在硬盘上找到那篇文章,看了看,发现是我记错了,不是GetLastError改变了现场数据,而是没有用GetLastError保存现场,更正一下。

      • At 2009.05.18 23:11, 青天白日梦 said:

        请问下,我安装了自己的SPI后,发现QQ登陆不了,主页打不开,但是,对用数据报写的一个简单的聊天程序,就能使用。这是什么原因?

        • At 2009.09.28 16:59, Randy said:

          API调用不出错未必不会覆盖LastError, Windows的内部实现有些代码是通过GetLastError辅助判断上一次的调用状态,所以如果LastError很重要,就需要及时保存(比如做APIHook),不能指望Windows能替你维持它的值直到下次出错。

          另外,LastError是线程相关的,参见:TEB.LastErrorValue

          (Required)
          (Required, will not be published)