什么样的库函数会对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标准的强化.
3
errno
初始线程中的值在程序启动时为零(errno
其他线程的初始值为不确定值),但任何库函数都不会将其设置为零.202)如果在本国际标准中的功能描述中没有记录errno
使用,errno
则可以通过库函数调用将值设置为非零,无论是否存在错误.202)因此,
errno
用于错误检查的程序应在库函数调用之前将其设置为零,然后在后续库函数调用之前检查它.当然,库函数可以保存输入值,errno
然后将其设置为零,只要原始值恢复,如果errno
在返回之前值仍然为零.
以前版本的C标准中的措辞没有提到线程,但在其他方面类似.
注意,fopen()
C标准中的描述没有提到errno
.因此,允许errno
按C标准设置.相比之下,该mbsrtowcs()
功能被记录为设置errno
为EILSEQ; 它可能无法将其设置为其他值,因为C标准说它不应该(尽管没有什么可以阻止实现,如果它对某些条件有更好的错误).
POSIX页面errno
说:
许多函数提供了错误号
errno
,其中包含类型int
并在其中定义.
errno
只有在调用明确声明要设置的函数之后,才能定义值,直到下一个函数调用更改它或者应用程序为其赋值.值errno
时,则说明是由函数的返回值有效的只应进行检查.申请应errno
通过列入来获得定义.此POSIX.1-2008卷中的任何功能都不应设置
errno
为0.errno
成功调用函数后的设置未指定,除非该函数的描述指定errno
不应修改.未指定
errno
是使用外部链接声明的宏还是标识符.如果为了访问实际对象而禁止宏定义,或者程序使用名称定义标识符errno
,则行为是未定义的.存储在errno中的符号值记录在所有相关页面的ERRORS部分中.
以前版本中的措辞是类似的.
文档主要告诉您哪个函数可以设置哪些值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标准的强化.
3
errno
初始线程中的值在程序启动时为零(errno
其他线程的初始值为不确定值),但任何库函数都不会将其设置为零.202)如果在本国际标准中的功能描述中没有记录errno
使用,errno
则可以通过库函数调用将值设置为非零,无论是否存在错误.202)因此,
errno
用于错误检查的程序应在库函数调用之前将其设置为零,然后在后续库函数调用之前检查它.当然,库函数可以保存输入值,errno
然后将其设置为零,只要原始值恢复,如果errno
在返回之前值仍然为零.
以前版本的C标准中的措辞没有提到线程,但在其他方面类似.
注意,fopen()
C标准中的描述没有提到errno
.因此,允许errno
按C标准设置.相比之下,该mbsrtowcs()
功能被记录为设置errno
为EILSEQ; 它可能无法将其设置为其他值,因为C标准说它不应该(尽管没有什么可以阻止实现,如果它对某些条件有更好的错误).
POSIX页面errno
说:
许多函数提供了错误号
errno
,其中包含类型int
并在其中定义.
errno
只有在调用明确声明要设置的函数之后,才能定义值,直到下一个函数调用更改它或者应用程序为其赋值.值errno
时,则说明是由函数的返回值有效的只应进行检查.申请应errno
通过列入来获得定义.此POSIX.1-2008卷中的任何功能都不应设置
errno
为0.errno
成功调用函数后的设置未指定,除非该函数的描述指定errno
不应修改.未指定
errno
是使用外部链接声明的宏还是标识符.如果为了访问实际对象而禁止宏定义,或者程序使用名称定义标识符errno
,则行为是未定义的.存储在errno中的符号值记录在所有相关页面的ERRORS部分中.
以前版本中的措辞是类似的.