为什么 glibc 的 fclose(NULL) 会导致分段错误而不是返回错误?
- 2024-11-14 08:29:00
- admin 原创
- 15
问题描述:
根据手册页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);
}
解决方案 1:
fclose
`FILE需要通过
fopen、标准流
stdin、
stdout或之一
stderr或其他实现定义的方式获得的指针作为其参数。空指针不是其中之一,因此行为未定义,就像
fclose((FILE *)0xdeadbeef)会一样。NULL在 C 中**并不特殊**;除了它保证与任何有效指针的比较不相等之外,它就像任何其他无效指针一样,并且使用它会调用未定义的行为,除非您将其传递给的接口作为其合同的一部分记录,并且该合同
NULL`对它具有某些特殊含义。
此外,返回错误是有效的(因为行为无论如何都是未定义的),但对于实现来说是有害的行为,因为它隐藏了未定义的行为。调用未定义行为的最佳结果始终是崩溃,因为它突出显示错误并使您能够修复它。大多数用户都fclose
不会检查错误返回值,我敢打赌,大多数愚蠢到传递给的人NULL
都fclose
不会聪明到检查的返回值fclose
。可以说人们应该通常检查的返回值fclose
,因为最后的刷新可能会失败,但对于仅为读取而打开的文件或fflush
之前手动调用过的文件fclose
(无论如何这是一个更聪明的习语,因为在您仍然打开文件时处理错误更容易)来说,这不是必需的。
解决方案 2:
fclose(NULL)
应该会成功。 free(NULL)
成功,因为这使得编写清理代码变得更容易。
遗憾的是,它的定义并非如此。因此您无法fclose(NULL)
在可移植程序中使用。(例如,请参阅http://pubs.opengroup.org/onlinepubs/9699919799/)。
正如其他人提到的,如果将 NULL 传递到错误的位置,您通常不希望返回错误。您需要一条警告消息,至少在调试/测试版本中需要。取消引用 NULL 会立即给您一条警告消息,并有机会收集识别编程错误的回溯 :)。在编程时,段错误是您可能遇到的最佳错误。C 有许多更微妙的错误,需要更长的时间来调试……
可以滥用错误返回来提高对编程错误的鲁棒性。但是,如果您担心软件崩溃会丢失数据,请注意,如果您的硬件断电,也可能发生完全相同的情况。这就是我们有自动保存的原因(因为 Unix 文本编辑器有两个字母的名称,如 ex 和 vi)。您的软件最好明显崩溃,而不是继续处于不一致的状态。
解决方案 3:
手册页中提到的错误是运行时错误,而不是编程错误。您不能直接将NULL
指针传递给任何需要指针的 API,并期望该 API 执行合理的操作。将指针传递NULL
给记录为需要指向数据的指针的函数是一个错误。
相关问题:在 C 或 C++ 中,我是否应该检查指针参数是否为 NULL/nullptr?
引用R.对这个问题的一个答案的评论:
...您似乎将操作环境中的异常情况(文件系统已满、内存不足、网络中断等)导致的错误与编程错误混淆了。在前一种情况下,健壮的程序当然需要能够妥善处理它们。在后一种情况下,健壮的程序首先就无法遇到它们。
解决方案 4:
这个fclose()
问题似乎是 FreeBSD 的遗留问题,并且被微软和 Linux 阵营不加批判地接受了。
但另一方面,HP、SGI、Solaris 和 CYGWIN 都处理fclose(NULL)
得合理。例如,man fclose
对于使用 newlib 而不是 OP 的 glibc 的 CYGWIN,声明:
如果成功则 fclose 返回 0(包括当 FP 为 NULL 或不是打开的文件时)
请参阅https://stackoverflow.com/a/8442421/318716了解相关讨论。
解决方案 5:
我认为手册页讨论的是底层文件描述符open
(当您调用时通过系统调用内部获取的文件描述符fopen
)无效,而不是您传递给的文件指针fclose
。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件