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/ 。