首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么调用unistd.h调用crypt()函数时将errno设置为ENOENT?

为什么调用unistd.h调用crypt()函数时将errno设置为ENOENT?
EN

Stack Overflow用户
提问于 2018-03-17 19:26:59
回答 1查看 230关注 0票数 0

我编写并运行了以下代码:

代码语言:javascript
复制
#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)。

这是输出:

代码语言:javascript
复制
errno = 0
abtAunjzvWWRQ
errno = 2
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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的操作(包括使用iostreamscstdio)。

孤立起来似乎有些奇怪,但这实际上是完全有道理的。例如,考虑一个需要参考配置文件(如果存在的话)的函数。它将包括代码,类似于:

代码语言:javascript
复制
FILE* config = fopen(configFileName, "r");
if (config) { /* Read the file */ }
else { /* Set default values */ }

如果配置文件不存在,它就不会被使用。没问题。但errno很可能是由fopen失败造成的。

这类事情在库函数中非常常见,它们在第一次调用时执行初始化。如果没有此规定,任何调用另一个库函数的库函数都必须在启动之前仔细保存errno,然后在结束时恢复它,除非报告了实际错误。我敢打赌你的功能不会那么做的:) -我的肯定不会。它很微妙而且容易出错。更好、更可审计的是实际采用的惯例:只有当函数确实报告错误时,errno才有效。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49341043

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档