Vdr*_*gon 19 c linux segmentation-fault fclose
根据手册页fclose(3)
:
返回值
成功完成后返回0.否则,
EOF
返回并设置全局变量errno
以指示错误.在任何一种情况下fclose()
,对流的任何进一步访问(包括另一次调用)都会导致未定义的行为.错误
EBADF
底层文件描述符fp
无效.该
fclose()
函数也可能失败并设置errno
为例程指定的任何错误close(2)
,write(2)
或fflush(3)
.
当然fclose(NULL)
应该失败,但我希望它能够errno
正常返回,而不是直接通过分段故障死亡.这种行为有什么原因吗?
提前致谢.
更新:我将把我的代码放在这里(strerror()
特别是我正在努力).
FILE *not_exist = NULL;
not_exist = fopen("nonexist", "r");
if(not_exist == NULL){
printError(errno);
}
if(fclose(not_exist) == EOF){
printError(errno);
}
Run Code Online (Sandbox Code Playgroud)
R..*_*R.. 27
fclose
要求作为其参数一个FILE
指针获得或者通过fopen
,标准流中的一个stdin
,stdout
或stderr
,或在一些其它实现定义方式.空指针不是其中之一,因此行为是未定义的,就像那样fclose((FILE *)0xdeadbeef)
.NULL在C中并不特殊 ; 除了一个事实,即它保证比较不等于任何有效的指针,它只是像任何其他无效的指针,并使用它调用时的界面你将它传递给文件作为合同的一部分,除了不确定的行为NULL
具有一定的它的特殊含义.
此外,返回错误将是有效的(因为行为未定义),但实现的有害行为,因为它隐藏了未定义的行为.调用未定义行为的最佳结果始终是崩溃,因为它突出显示错误并使您能够修复它.大多数用户fclose
都没有检查错误返回值,而且我打赌大多数人愚蠢地传递NULL
给他们fclose
并不会足够聪明地检查返回值fclose
.一种说法可以提出,人们应该检查返回值fclose
在一般情况下,因为最后的冲洗可能会失败,但是这是没有必要的是仅进行读取操作,或者如果文件fflush
手动之前被称为fclose
(这是一个聪明的成语呢因为在你打开文件时更容易处理错误.
fclose(NULL)
应该成功。 free(NULL)
成功,因为这样可以更轻松地编写清除代码。
遗憾的是,这不是它的定义方式。因此,您不能fclose(NULL)
在可移植程序中使用。(例如,参见http://pubs.opengroup.org/onlinepubs/9699919799/)。
正如其他人提到的那样,如果将NULL传递到错误的位置,通常不希望返回错误。您至少在调试/测试版本中需要警告消息。取消引用NULL会给您立即警告消息,并有机会收集可识别编程错误的回溯信息:)。在编程时,段错误就是您可能会遇到的最佳错误。C还有许多细微的错误,需要花费更长的时间进行调试...
可以滥用错误返回值来提高针对编程错误的鲁棒性。但是,如果您担心软件崩溃会丢失数据,请注意,如果硬件断电,可能会发生完全相同的情况。这就是我们具有自动保存功能的原因(因为Unix文本编辑器具有两个字母的名称,例如ex和vi)。最好还是让软件明显崩溃,而不是继续出现不一致的状态。
手册页谈论的错误是运行时错误,而不是编程错误。您不能只是传递NULL
到任何期望指针的 API 并期望该 API 做一些合理的事情。将NULL
指针传递给记录为需要数据指针的函数是一个错误。
相关问题:在 C 或 C++ 中,我应该根据 NULL/nullptr 检查指针参数吗?
...您似乎将操作环境中的异常情况(fs 已满、内存不足、网络故障等)引起的错误与编程错误混淆。在前一种情况下,一个健壮的程序当然需要能够优雅地处理它们。在后者中,强大的程序首先无法体验它们。
这个fclose()
问题似乎是 FreeBSD 的遗留问题,并被 Microsoft 和 Linux 阵营不加批判地接受。
但另一方面,HP、SGI、Solaris 和 CYGWIN 都可以fclose(NULL)
合理处理。例如,man fclose
对于 CYGWIN,它使用 newlib 而不是 OP 的 glibc,声明:
如果成功,fclose 返回 0(包括 FP 为 NULL 或不是打开的文件时)
有关相关讨论,请参阅/sf/answers/590969501/ 。