我在处理 HRESULT 返回值时遇到了一些非常尴尬的事情,似乎成功为 0,失败为 1。这背后的逻辑是什么?
我实际上尝试过if(!hr)
并且失败得很惨,浪费了我生命中的一个小时,直到我发现实际成功的 retval 为 0。我想把想到这个的人称为白痴,但我会试着冷静下来——希望有人会阐明这一公约。
HRESULT 的最初目的是正式列出供公众和 Microsoft 内部使用的错误代码范围,以防止 OS/2 操作系统的不同子系统中的错误代码发生冲突。
这就是为什么值 0(HRESULT 的最高位)意味着“没有错误”,即成功。
但是应该小心,因为 HRESULT 可能将最高位设置为 0,而其他位设置为不同于 0。这意味着,检查if(0 == hr) { ... }
可能不适用于某些成功的情况。检查成功的正确方法是if(0 <= hr) { ... }
.
维基百科有更详细的信息。
SUCCEEDED
和FAILED
宏可用于在处理 HRESULT 值时避免错误。if(0 <= hr) { ... }
和if(SUCCEEDED(hr)) { ... }
基本上是一样的东西。
你又误会了,因为几乎所有系统中的所有系统错误,返回值 0 都是成功,非零返回值表示错误代码,使用这种技术,我们可以只用一个返回值报告不同类型的错误。但是因为HRESULT
我们有>= 0
成功和<0
错误,所以从角度来看,1 的值HRESULT
是成功而不是错误。HRESULT
>0 表示警告或有关功能的信息,0 表示绝对成功,<0 表示错误。HRESULT 的布局是:
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+-+-+-+-+-+---------------------+-------------------------------+
|S|R|C|N|r| Facility | Code |
+-+-+-+-+-+---------------------+-------------------------------+
where
S - Severity - indicates success/fail
0 - Success
1 - Fail (COERROR)
R - reserved portion of the facility code, corresponds to NT's second severity bit.
C - reserved portion of the facility code, corresponds to NT's C field.
N - reserved portion of the facility code. Used to indicate a mapped NT status value.
r - reserved portion of the facility code. Reserved for internal use. Used to
indicate HRESULT values that are not status values, but are instead message
ids for display strings.
Facility - is the facility code
Code - is the facility's status code
如您所见,这是对自定义错误代码、警告和信息提供非常合理的支持的最佳设计之一
您通常应该使用SUCCEEDED
andFAILED
宏来测试HRESULT
s,因为虽然绝大多数函数返回S_OK
(value = 0) 表示成功,但也有一些非零成功值(例如S_FALSE
)。通常,您需要明确地测试这些值,以防它们可能被返回,但在一般情况下,使用SUCCEEDED
更清晰、更安全。
if (SUCCEEDED(hr)) { // ...