当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《什么样的错误将"错误"设置为非零?为什么fopen()设置"errno"而fputc()没有?》经验,为你挑选了1个好方法。

什么样的库函数会对errno产生什么样的错误并将其设置为非零值?在我的下面的程序中,我打算用if(errno!=0)一个条件来检查我使用的库函数是否正常运行,这就是我找到的(参见下面的代码):

首先我用来if(errno!=0)测试文件是否已成功打开fopen().如果我尝试打开一个不存在的文件,则errno设置为非零(在我的情况下为2),并通过打印errno每个阶段的值来验证它.但是,如果我打开现有文件,则errno的值保持为零,因为fopen()正确打开文件.在这件事上,if(errno!=0)作为if(pFile==NULL)我所评论的完美替代品.

如果文件成功打开,errno静止0,则控件移动到第一个else块.这是我发现关于行为的混淆的地方errno.在这里,由于我已经在r(读)模式下打开文件并尝试使用它来写入fputc(),我希望得到的写错误设置errno为非零,就像fopen()它无法成功打开文件时设置的那样.但errno即使在写入失败后,该值仍然为零fputc().(这可以通过errno错误写入后的打印值来验证).

为什么会这样?为什么一个函数fopen()设置了I/O错误设置errno其他函数所面临的while写错误fputc()不影响errno?如果是这样,我们怎样才能可靠地errno用作错误指标?我是否使用errno来测试fopen()是否成功运行,而不是"if(pFile == NULL)"不明智?我将非常感谢您对此的分析答案.

#include 
#include 

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; 
}

Jonathan Lef.. 9

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

    没有库函数设置errno为零.

    errno在功能指示发生错误时进行测试(并记录设置的功能errno).

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

第二点至关重要; 例如,在Solaris上,在通道不是终端的许多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尽早捕获该值:

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

永远不要宣告errno自己; 总是习惯#include 这样做.

我不清楚为什么你的代码没有在fputc()通话中出错.在我的Mac OS X 10.8.3系统上,等效代码失败,errno设置为9(EBADF)'错误的文件描述符'.


这记录在哪里?它符合C标准,并受到POSIX标准的强化.

ISO/IEC 9899:2011§7.5错误

3 errno初始线程中的值在程序启动时为零(errno其他线程的初始值为不确定值),但任何库函数都不会将其设置为零.202)如果在本国际标准中的功能描述中没有记录errno使用,errno则可以通过库函数调用将值设置为非零,无论是否存在错误.

202)因此,errno用于错误检查的程序应在库函数调用之前将其设置为零,然后在后续库函数调用之前检查它.当然,库函数可以保存输入值,errno然后将其设置为零,只要原始值恢复,如果errno在返回之前值仍然为零.

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

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

POSIX 2008

POSIX页面errno说:

许多函数提供了错误号errno,其中包含类型int并在其中定义.errno只有在调用明确声明要设置的函数之后,才能定义值,直到下一个函数调用更改它或者应用程序为其赋值.值errno时,则说明是由函数的返回值有效的只应进行检查.申请应errno通过列入来获得定义.此POSIX.1-2008卷中的任何功能都不应设置errno为0. errno成功调用函数后的设置未指定,除非该函数的描述指定errno不应修改.

未指定errno是使用外部链接声明的宏还是标识符.如果为了访问实际对象而禁止宏定义,或者程序使用名称定义标识符errno,则行为是未定义的.

存储在errno中的符号值记录在所有相关页面的ERRORS部分中.

以前版本中的措辞是类似的.



1> Jonathan Lef..:

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

    没有库函数设置errno为零.

    errno在功能指示发生错误时进行测试(并记录设置的功能errno).

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

第二点至关重要; 例如,在Solaris上,在通道不是终端的许多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尽早捕获该值:

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

永远不要宣告errno自己; 总是习惯#include 这样做.

我不清楚为什么你的代码没有在fputc()通话中出错.在我的Mac OS X 10.8.3系统上,等效代码失败,errno设置为9(EBADF)'错误的文件描述符'.


这记录在哪里?它符合C标准,并受到POSIX标准的强化.

ISO/IEC 9899:2011§7.5错误

3 errno初始线程中的值在程序启动时为零(errno其他线程的初始值为不确定值),但任何库函数都不会将其设置为零.202)如果在本国际标准中的功能描述中没有记录errno使用,errno则可以通过库函数调用将值设置为非零,无论是否存在错误.

202)因此,errno用于错误检查的程序应在库函数调用之前将其设置为零,然后在后续库函数调用之前检查它.当然,库函数可以保存输入值,errno然后将其设置为零,只要原始值恢复,如果errno在返回之前值仍然为零.

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

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

POSIX 2008

POSIX页面errno说:

许多函数提供了错误号errno,其中包含类型int并在其中定义.errno只有在调用明确声明要设置的函数之后,才能定义值,直到下一个函数调用更改它或者应用程序为其赋值.值errno时,则说明是由函数的返回值有效的只应进行检查.申请应errno通过列入来获得定义.此POSIX.1-2008卷中的任何功能都不应设置errno为0. errno成功调用函数后的设置未指定,除非该函数的描述指定errno不应修改.

未指定errno是使用外部链接声明的宏还是标识符.如果为了访问实际对象而禁止宏定义,或者程序使用名称定义标识符errno,则行为是未定义的.

存储在errno中的符号值记录在所有相关页面的ERRORS部分中.

以前版本中的措辞是类似的.

推荐阅读
有风吹过best
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有