繁体   English   中英

为什么从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()函数后,其设置为2ENOENT )。

这是输出:

errno = 0
abtAunjzvWWRQ
errno = 2

这是C标准关于errno (第7.5节,第3段,重点已添加。)

程序启动时,初始线程中errno的值为零(其他线程中errno的初始值为不确定的值),但是任何库函数都不会将其设置为零。 无论是否存在错误都可以通过库函数调用将errno的值设置为非零 ,前提是在此国际标准的函数描述中未记录errno的使用。

这是Posix说的(部分)(再次强调):

errno时,则说明是由函数的返回值有效的只应检查......在这卷POSIX.1-2008的无功能将设置errno为0 的设置errno成功调用函数后除非该函数的说明指定errno不得修改,否则指定。

crypt是Posix函数(如unistd.h存在所示)。 该描述未指定errno不应被修改。 可能是这样,过去是。

简而言之,除非函数明确报告了错误并且已记录该函数设置errno ,否则切勿尝试使用errno的值。 在这种情况下,请确保在调用该函数之后,执行可能设置errno任何其他操作(包括使用iostreamscstdio )之前立即使用它(或保存其值)。

孤立地看这似乎有些奇怪,但实际上是很合理的。 例如,考虑一个需要查阅配置文件的功能(如果存在)。 它将包含类似以下的代码:

FILE* config = fopen(configFileName, "r");
if (config) { /* Read the file */ }
else { /* Set default values */ }

如果配置文件不存在,则根本不会使用它。 没问题。 但是errno可能是由fopen失败引起的。

这种事情在库函数中很常见,库函数在第一次调用时执行初始化。 如果不是用于此规定,则调用另一个库函数的任何库函数都必须在启动之前仔细保存errno ,然后在结束时将其还原,除非已报告实际错误。 我敢打赌,您的功能不会这样做:)-我的当然不会。 这很容易出错。 实际采用的约定更好,更易于审核: errno仅在函数明确报告错误时才有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM