我编写并运行了以下代码:
#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发布于 2018-03-17 22:03:31
以下是C标准对errno的看法(§7.5,第3段,重点补充)。
在程序启动时,初始线程中的
errno值为零(其他线程中的errno初始值是一个不定值),但任何库函数都不会将其设置为零。如果在本国际标准中对函数的描述中未记录errno的使用,则无论是否存在错误,库函数调用都可以将的值设置为非零。
下面是Posix说的(部分)内容(再次强调):
只有当函数的返回值指示为有效时,才应检查errno的值。在本卷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,然后在结束时恢复它,除非报告了实际错误。我敢打赌你的功能不会那么做的:) -我的肯定不会。它很微妙而且容易出错。更好、更可审计的是实际采用的惯例:只有当函数确实报告错误时,errno才有效。
https://stackoverflow.com/questions/49341043
复制相似问题