GetLastError()、errno、FormatMessageA() 和 strerror_s()?
Posted
技术标签:
【中文标题】GetLastError()、errno、FormatMessageA() 和 strerror_s()?【英文标题】:GetLastError(), errno, FormatMessageA() and strerror_s()? 【发布时间】:2013-12-02 03:19:08 【问题描述】:我对@987654323@ 和errno
之间的确切关系感到困惑。它们是相同的数值,还是完全不同的东西?我怎么知道我应该检查哪一项?
如果我想将错误代码转换为字符串进行调试,我可以将FormatMessageA()
与strerror_s()
互换使用吗?
最后,WSAGetLastError()
是否总是返回与 GetLastError()
相同的值,还是它们都返回不同的值?
【问题讨论】:
GetLastError
和 FormatMessage
用于 Win32 错误。 errno
和 strerror
用于 C 运行时错误。他们是无关的。每个函数都记录了它设置的错误代码。
Is WSAGetLastError() just an alias for GetLastError()? 的可能重复项
@RaymondChen 但套接字错误不是 c-runtime。无论如何,我在我的程序中成功地使用了errno
related 函数。这是否意味着在 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()?的主要内容,如果未能解决你的问题,请参考以下文章
CString 赋值正在改变 GetLastError() 的值