我已经编写并运行以下代码:
#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
答案 0 :(得分:3)
以下是C标准对errno
所说的内容(§7.5,第3段,强调补充。)
初始线程中
errno
的值在程序启动时为零 (其他线程中errno
的初始值是不确定的 值),但永远不会被任何库函数设置为零。 价值 可以通过库函数调用将errno
设置为非零,无论是否 如果没有记录errno
的使用,则不会出现错误 在本国际标准中对功能的描述中。
这是Posix says(再次强调添加)的部分内容:
errno
的值只有在函数的返回值表示有效时才应进行检查。...此POSIX.1-2008卷中的任何函数都不应将errno
设置为0。 成功调用函数后errno
的设置未指定,除非该函数的描述指定不应修改errno
。
crypt
是Posix函数(由其在unistd.h
中的存在表示)。该描述未指定不应修改errno
。所以它可能是,它是。
简而言之,从不尝试使用errno
的值,除非函数已明确报告错误并记录该函数以设置errno
。在这种情况下,请确保在调用该函数后立即使用它(或保存其值),并在执行可能设置errno
的任何其他操作之前(包括使用iostreams
和{ {1}})。
这可能在孤立中看起来有点奇怪,但它实际上非常有意义。例如,考虑一个需要查询配置文件的函数(如果存在)。它将包括类似的代码:
cstdio
如果配置文件不存在,则不会被使用。没问题。但FILE* config = fopen(configFileName, "r");
if (config) { /* Read the file */ }
else { /* Set default values */ }
可能已由errno
失败设置{/ 1}}。
这种事情在库函数中很常见,它们在第一次调用时执行初始化。如果不是这个规定,任何调用另一个库函数的库函数都必须在开始之前小心保存fopen
,然后在结束时将其恢复,除非报告实际错误。我敢打赌你的功能不会这样做:) - 我当然不会。它很狡猾,容易出错。实际采用的约定更好,更可审计:errno
仅在函数明确报告错误时才有效。