为什么从 unistd.h 调用 crypt() 函数会将 errno 设置为 ENOENT?
Why does a call to the crypt() function from unistd.h set the errno to ENOENT?
我写了 运行 以下代码:
#define _XOPEN_SOURCE
#include <iostream>
#include <unistd.h>
int main()
{
std::cout << "errno = " << errno << std::endl;
std::cout << crypt("sometext", "ab") << std::endl;
std::cout << "errno = " << errno <<std:: endl;
return 0;
}
errno
的初始值是 0
,但在调用 crypt()
函数后它被设置为 2
(ENOENT).
这是输出:
errno = 0
abtAunjzvWWRQ
errno = 2
以下是 C 标准关于 errno
的内容(§7.5,第 3 段,强调已添加。)
The value of errno
in the initial thread is zero at program startup
(the initial value of errno
in other threads is an indeterminate
value), but is never set to zero by any library function. The value
of errno
may be set to nonzero by a library function call whether or
not there is an error, provided the use of errno
is not documented
in the description of the function in this International Standard.
这里是(部分)Posix says(再次强调):
errno
的值只有在函数的 return 值表明它有效时才应检查。... POSIX 本卷中没有函数。1-2008应将 errno
设置为 0。 未指定成功调用函数后 errno
的设置 除非该函数的描述指定 errno
不得修改。
crypt
是一个 Posix 函数(如它在 unistd.h
中的存在所示)。描述中没有指定 errno
不得修改。可能是这样,而且确实如此。
简而言之,从不 尝试使用 errno
的值,除非函数已明确报告错误并且该函数被记录为设置 errno
.在这种情况下,请确保在调用该函数后立即使用它(或保存其值),然后再执行任何可能设置 errno
的操作(包括使用 iostreams
和 cstdio
).
单独来看这一切似乎有点奇怪,但实际上非常有道理。例如,考虑一个需要查询配置文件(如果存在)的函数。它将包含如下代码:
FILE* config = fopen(configFileName, "r");
if (config) { /* Read the file */ }
else { /* Set default values */ }
如果配置文件不存在,它就不会被使用。没问题。但是 errno
很可能是由 fopen
失败设置的。
这种事情在库函数中很常见,库函数在第一次调用时执行初始化。如果不是这个规定,任何调用另一个库函数的库函数都必须在开始之前小心地保存 errno
,然后在结束时恢复它,除非报告了实际错误。我敢打赌您的函数不会那样做 :) ——我的肯定不会。这很繁琐 error-prone。实际采用的约定更好、更易于审核:errno
仅在函数明确报告错误时才有效。
我写了 运行 以下代码:
#define _XOPEN_SOURCE
#include <iostream>
#include <unistd.h>
int main()
{
std::cout << "errno = " << errno << std::endl;
std::cout << crypt("sometext", "ab") << std::endl;
std::cout << "errno = " << errno <<std:: endl;
return 0;
}
errno
的初始值是 0
,但在调用 crypt()
函数后它被设置为 2
(ENOENT).
这是输出:
errno = 0
abtAunjzvWWRQ
errno = 2
以下是 C 标准关于 errno
的内容(§7.5,第 3 段,强调已添加。)
The value of
errno
in the initial thread is zero at program startup (the initial value oferrno
in other threads is an indeterminate value), but is never set to zero by any library function. The value oferrno
may be set to nonzero by a library function call whether or not there is an error, provided the use oferrno
is not documented in the description of the function in this International Standard.
这里是(部分)Posix says(再次强调):
errno
的值只有在函数的 return 值表明它有效时才应检查。... POSIX 本卷中没有函数。1-2008应将 errno
设置为 0。 未指定成功调用函数后 errno
的设置 除非该函数的描述指定 errno
不得修改。
crypt
是一个 Posix 函数(如它在 unistd.h
中的存在所示)。描述中没有指定 errno
不得修改。可能是这样,而且确实如此。
简而言之,从不 尝试使用 errno
的值,除非函数已明确报告错误并且该函数被记录为设置 errno
.在这种情况下,请确保在调用该函数后立即使用它(或保存其值),然后再执行任何可能设置 errno
的操作(包括使用 iostreams
和 cstdio
).
单独来看这一切似乎有点奇怪,但实际上非常有道理。例如,考虑一个需要查询配置文件(如果存在)的函数。它将包含如下代码:
FILE* config = fopen(configFileName, "r");
if (config) { /* Read the file */ }
else { /* Set default values */ }
如果配置文件不存在,它就不会被使用。没问题。但是 errno
很可能是由 fopen
失败设置的。
这种事情在库函数中很常见,库函数在第一次调用时执行初始化。如果不是这个规定,任何调用另一个库函数的库函数都必须在开始之前小心地保存 errno
,然后在结束时恢复它,除非报告了实际错误。我敢打赌您的函数不会那样做 :) ——我的肯定不会。这很繁琐 error-prone。实际采用的约定更好、更易于审核:errno
仅在函数明确报告错误时才有效。