GetLastError()、errno、FormatMessageA() 和 strerror_s()?

Posted

技术标签:

【中文标题】GetLastError()、errno、FormatMessageA() 和 strerror_s()?【英文标题】:GetLastError(), errno, FormatMessageA() and strerror_s()? 【发布时间】:2013-12-02 03:19:08 【问题描述】:

我对@9​​87654323@ 和errno 之间的确切关系感到困惑。它们是相同的数值,还是完全不同的东西?我怎么知道我应该检查哪一项?

如果我想将错误代码转换为字符串进行调试,我可以将FormatMessageA()strerror_s() 互换使用吗?

最后,WSAGetLastError() 是否总是返回与 GetLastError() 相同的值,还是它们都返回不同的值?

【问题讨论】:

GetLastErrorFormatMessage 用于 Win32 错误。 errnostrerror 用于 C 运行时错误。他们是无关的。每个函数都记录了它设置的错误代码。 Is WSAGetLastError() just an alias for GetLastError()? 的可能重复项 @RaymondChen 但套接字错误不是 c-runtime。无论如何,我在我的程序中成功地使用了errnorelated 函数。这是否意味着在 Windows 上 perror()strerror() 与 Win32 API 不同?这是一个非常有趣的问题:我现在正在从 GNU/Linux 移植一个小应用程序,如果 strerror() 突然拒绝打印网络错误,那就不好了。 @Hi-Angel The FormatMessage function can be used to obtain the message string for the returned error. @nodakai 我知道,我不是这个意思。我想知道是否可以使用 errno 来获取至少一个套接字错误。但现在我已经知道,那不是。 Tbh 我不知道为什么有人可以在 Windows 中使用errno。原则上我会遇到什么样的错误?在 *nix 中,我几乎可以通过 errno 获得所有内容,但 Windows 似乎根本没有使用它。虽然是标准。这很可悲。 【参考方案1】:

GetLastError 和 errno 没有关系。

GetLastError 获取由 Windows API 函数设置的最后一个错误(针对当前线程),而 errno 包含由 C 运行时库函数存储到其中的最后一个错误(也针对当前线程)。

几乎所有向调用者返回错误的 WinAPI 函数都会在发生错误时以某种方式指示,然后通过调用 GetLastError 为调用者设置错误。 注意:并非所有 WinAPI 函数都向其调用者返回错误。

例如,WinAPI 函数 CreateFile 的文档说:

如果函数成功,则返回值是指定文件、设备、命名管道或邮件槽的打开句柄。如果函数失败,则返回值为 INVALID_HANDLE_VALUE。要获取扩展的错误信息,请调用 GetLastError。

将错误返回给调用者的 C 运行时库函数将以某种方式指示何时发生错误,然后将值存储在 errno 中。 注意:并非所有 C 运行时库函数都向其调用者返回错误。

例如,C 运行时库函数 sqrt 的文档说:

sqrt 函数计算其参数的非负平方根。如果参数为负数,则会发生域错误。

关于域错误的文档说:

发生域错误时,函数返回实现定义的值;并且值 EDOM 存储在 errno 中。

GetLastError 返回的值与 errno 中存储的值不同,所以我认为这回答了关于使用 FormatMessage 和 strerror_s 的问题。

我不知道 WSAGetLastError 是否总是返回与 GetLastError 相同的值(尽管我注意到 GetLastError 返回的错误代码列表确实包含 WSAGetLastError 可以返回的错误代码)。见System Error Codes (9000-11999)。如果您查看从 10000 左右开始的错误代码,您将看到 WSAGetLastError 错误代码。

无论如何,我个人不会依赖它们返回相同的值。为什么会有用?只需按照文档并为 Winsock2 函数调用 WSAGetLastError,为其他 WinAPI 函数调用 GetLastError。注意:您可以对任一函数返回的错误代码使用 FormatMessage。

【讨论】:

我知道最初的问题并没有考虑到 Linux,但由于 C 运行时在 Windows 和 Linux 中都很常见,而且 Win32 API 显然在 Linux 上不存在,使用 errno 是否有用案例? @ZoomIn 对不起,我不明白。 “在这种情况下使用 errno 有用吗”是什么意思。 我要问的是'errno 是否替换了Linux 上的GetLastError()'? @ZoomIn 我不明白你所说的“替换”是什么意思,有两组函数有两种不同的指示错误的方式。正如我在对原始问题的回答中所说,“如果你调用一个 winapi 函数,比如 CreateFile,你检查 GetLastError(假设函数调用失败),而如果你调用一个 C 标准库函数,比如 sqrt,你检查 errno (再次假设调用失败)”。 抱歉,我的意思是显然 Linux 上没有 Win32 API,所以我们只剩下 C 标准库函数来获取错误。似乎这是作为替代方案的唯一方法。我只是想问是否还有其他可以在 Linux 中使用的东西。

以上是关于GetLastError()、errno、FormatMessageA() 和 strerror_s()?的主要内容,如果未能解决你的问题,请参考以下文章

从 C# 访问 C 全局变量 'errno'

GetLastError的返回值

GetLastError() 将 0 返回到失败的窗口句柄

CString 赋值正在改变 GetLastError() 的值

WTSQueryUserToken 失败,getlasterror() 返回 1723

django app 多硬盘 [Errno 18] 无效的跨设备链接