gpt4 book ai didi

c - 什么样的错误将 "errno"设置为非零?为什么 fopen() 设置 "errno"而 fputc() 不设置?

转载 作者:太空狗 更新时间:2023-10-29 17:18:27 29 4
gpt4 key购买 nike

什么样的库函数所面临的什么样的错误会影响errno并将其设置为非零值?在我下面的程序中,我打算使用 if(errno!=0) 作为条件来检查我使用的库函数是否正常运行,这是我发现的(见下面的代码):

首先,我使用 if(errno!=0) 来测试文件是否已使用 fopen() 成功打开。如果我尝试打开一个不存在的文件,然后 errno 设置为非零(在我的例子中为 2)并且通过打印出 errno 的值来验证它在每个阶段。但是,如果我打开一个现有文件,则 errno 的值保持为零,因为 fopen() 正确打开文件。在这件事上,if(errno!=0) 完美替代了我已注释掉的 if(pFile==NULL)

如果文件打开成功,errno 仍然是 0,控件将移动到第一个 else block 。这是我对 errno 的行为感到困惑的地方。在这里,由于我已经在 r(read) 模式下打开文件并尝试使用 fputc() 对其进行写入,因此我希望生成的写入错误设置为 errno 设置为非零,就像它在无法成功打开文件时由 fopen() 设置的一样。但是即使在使用 fputc() 写入失败之后,errno 的值仍然为零。 (这可以通过在错误写入后打印 errno 的值来验证)。

为什么会这样?为什么一个函数 fopen() 设置了 errno 会遇到 I/O 错误,而其他函数 fputc() 会遇到写入错误,但不会影响 错误号?如果是这样,我们如何可靠地使用 errno 作为错误指示符? 我使用 errno 来测试 fopen() 是否成功,而不是“if(pFile==NULL)”是否不明智?我将感谢您对此的分析性回答。

#include <stdio.h>
#include <errno.h>

int main ()
{

FILE * pFile;
printf("%d\n",errno);

pFile = fopen("D:\\decrypt.txt","r");
printf("%d\n",errno); // Prints 0 if fopen() successful,else 2

//if(pFile==NULL) perror("Error opening file");

if (errno!=0) perror ("Error opening file");

else
{
fputc ('x',pFile);
printf("%d\n",errno); //errno shows 0 even after write error

//if (ferror (pFile))
if (errno!=0) //Condition evaluates false even if faulty write
{
printf ("Error Writing to decrypt.txt\n");
}
fclose (pFile);

}
return 0;
}

最佳答案

文档主要告诉您哪个函数可以设置 errno 中的哪些值, 但有一些规则你需要知道:

  1. 没有库函数集 errno归零。
  2. 只对测试errno有效当函数指示发生错误时(并且函数被记录为设置 errno )。

第一点意味着,如果您想知道,例如,您是否从 strtol() 得到了一个错误。 , 你必须设置 errno在调用它之前为 0。

第二点很关键;例如,在 Solaris 上,当 channel 不是终端时经过多次 I/O 操作后,errno 的设置将是 ENOTTY (不是终端)。没有错误;没有失败;但基于 errno 的后续操作单独(而不是 I/O 操作报告的状态)会让您认为一切都失败了。

因此,在您的代码中,fopen()来电可留errno作为一个非零值,即使它成功地创建了文件流。你必须使用:

const char filename[] = "D:\\crypt.txt";
if ((pFile = fopen(filename, "r")) == 0)
{
fprintf(stderr, "Failed to open %s for reading (%d: %s)\n",
filename, errno, strerror(errno));
...return or exit...
}

注意:如果你需要调用一个可以改变 errno 的函数, 尽早捕获值(value):

    int errnum = errno;
fprintf(stderr, "Failed to open %s for reading (%d: %s)\n",
filename, errnum, strerror(errnum));

永远不要声明errno你自己;始终使用 #include <errno.h>去做。

我不清楚为什么您的代码在 fputc() 上没有出错称呼。在我的 Mac OS X 10.8.3 系统上,等效代码失败并返回 errno。设置为 9 (EBADF) '错误的文件描述符'。


这是在哪里记录的?它符合 C 标准,并由 POSIX 标准加强。

ISO/IEC 9899:2011 §7.5 错误 <errno.h>

¶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.202) 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.

202) Thus, a program that uses errno for error checking should set it to zero before a library function call, then inspect it before a subsequent library function call. Of course, a library function can save the value of errno on entry and then set it to zero, as long as the original value is restored if errno’s value is still zero just before the return.

C 标准以前版本的措辞没有提到线程,但其他方面类似。

请注意 fopen() 的描述C标准中没有提到errno .因此,允许设置 errno按照C标准。相比之下,mbsrtowcs()函数记录为设置 errno至 EILSEQ;它可能无法将其设置为其他值,因为 C 标准说它不应该(尽管如果在某些条件下有更好的错误,没有什么可以阻止实现这样做)。

POSIX 2008

errno 的 POSIX 页面说:

Many functions provide an error number in errno, which has type int and is defined in <errno.h>. The value of errno shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value. The value of errno should only be examined when it is indicated to be valid by a function's return value. Applications shall obtain the definition of errno by the inclusion of <errno.h>. No function in this volume of POSIX.1-2008 shall set errno to 0. The setting of errno after a successful call to a function is unspecified unless the description of that function specifies that errno shall not be modified.

It is unspecified whether errno is a macro or an identifier declared with external linkage. If a macro definition is suppressed in order to access an actual object, or a program defines an identifier with the name errno, the behavior is undefined.

The symbolic values stored in errno are documented in the ERRORS sections on all relevant pages.

之前版本的措辞类似。

关于c - 什么样的错误将 "errno"设置为非零?为什么 fopen() 设置 "errno"而 fputc() 不设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16507816/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com