报告错误以及有关失败的其他信息
除了失败/成功返回值之外,某些 API 调用还会设置失败时的最后一个错误(例如 CreateWindow )。该文档通常包含以下标准措辞:
如果函数成功,则返回值为 <API 特定的成功值> 。
如果函数失败,则返回值为 <API 特定的错误值> 。要获取扩展错误信息,请调用 GetLastError 。
if ( CreateWindowW( ... ) == NULL ) {
// Failure: get additional information.
DWORD dwError = GetLastError();
} else {
// Success: must not call GetLastError.
}
**至关重要的是你立即致电 GetLastError()
。**最后一个错误代码可以被任何其他函数覆盖,因此如果在失败的函数和对 GetLastError()
的调用之间有额外的函数调用,则 GetLastError()
的返回将不再可靠。处理 C++构造函数时要格外小心。
获得错误代码后,你需要解释它。你可以在系统错误代码(Windows)页面上获得 MSDN 上的错误代码的完整列表。或者,你可以查看系统头文件; 所有错误代码常量的文件是 winerror.h
。 (如果你使用的是适用于 Windows 8 或更高版本的 Microsoft 官方 SDK,则它位于 include 文件夹的 shared
子文件夹中。)
关于在其他编程语言中调用 GetLastError()
的注意事项
.net 语言(C#,VB 等)
使用 .net,你不应该直接 P / Invoke 到 GetLastError()
。这是因为 .net 运行时将在你背后的同一个线程上进行其他 Windows API 调用。例如,如果垃圾收集器找到了不再使用的足够内存,则可能会调用 VirtualFree()
,这可能发生在你的预期函数调用和你对 GetLastError()
的调用之间。
相反,.net 提供了 Marshal.GetLastWin32Error()
函数,它将从你自己进行的上一次 P / Invoke 调用中检索最后一个错误。使用此代替直接调用 GetLastError()
。
(.net 似乎并没有阻止你导入 GetLastError()
;我不知道为什么。)
走
Go 提供的用于调用 DLL 函数的各种工具(位于包 syscall
和 package golang.org/x/sys/windows
中)返回三个值:r1
,r2
和 err
。r2
从未使用过; 你可以在那里使用空白标识符。r1
是函数的返回值。err
是调用 GetLastError()
的结果,但转换为实现 error
的类型,因此你可以将其传递给调用函数来处理。
因为 Go 不知道何时调用 GetLastError()
而不知道何时调用 GetLastError()
,它将始终返回非 nil
错误。因此,典型的 Go 错误处理成语
r1, _, err := syscall.Syscall12(CreateWindowW.Addr(), ...)
if err != nil {
// handle err
}
// use r1
不管用。相反,你必须检查 r1
,就像你在 C 中一样,并且如果这表明函数返回了错误,则只使用 err
:
r1, _, err := syscall.Syscall12(CreateWindowW.Addr(), ...)
if r1 == 0 {
// handle err
}
// use r1