当前位置: 首页 > 面试题库 >

为什么glibc的fclose(NULL)会导致分段错误而不是返回错误?

蓬祺
2023-03-14
问题内容

根据手册页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);
}

问题答案:

fclose要求作为其参数一个FILE指针通过获得任一fopen,标准流中的一个stdinstdoutstderr,或在一些其它实现定义方式。空指针不是其中之一,因此行为是不确定的,就像是fclose((FILE *)0xdeadbeef)这样。 NULL 在C语言中 并不特殊
;除了一个事实,即它保证比较不等于任何有效的指针,它只是像任何其他无效的指针,并使用它调用时的界面你将它传递给文件作为合同的一部分,除了不确定的行为NULL具有一定的特殊的意义。

此外,返回错误将是有效的(因为无论如何该行为都是未定义的),但是对于实现来说是有害的,因为它 隐藏了未定义的行为
。调用未定义行为的最佳结果始终是崩溃,因为它会突出显示错误并允许您对其进行修复。的大多数用户fclose不会检查错误的返回值,因此我敢打赌大多数人会愚蠢到要传递NULLfclose,而他们不会足够聪明地检查的返回值fclose。由于最终的刷新可能会失败,因此人们可能会争辩说人们通常
应该
检查的返回值fclose,但是对于仅用于读取而打开的文件,或者如果fflush之前被手动调用的文件,则不需要这样做。fclose(无论如何这都是一个更聪明的习惯,因为在打开文件的同时更容易处理错误)。



 类似资料:
  • 我正在用Python实现Kosaraju的强连接组件(SCC)图搜索算法。 这个程序在小数据集上运行得很好,但当我在一个超大图形(超过800000个节点)上运行它时,它会显示“分段错误”。 原因可能是什么?非常感谢。 附加信息:首先,我在超大数据集中运行时出现了这个错误: 然后我重置递归限制使用 但是有一个“分割错误” 相信我,这不是一个无限循环,它在相对较小的数据上正确运行。有可能是程序耗尽了资

  • 问题内容: 遇到一个错误地使用 而不是 在其代码中的人,它没有显示为编译错误。 是因为 是相同的 ? 问题答案: 没有编译错误,因为它是有效的(尽管相当无用) 一元运算符 ,其使用方式与以下方式相同: Java语言规范中的相关部分是Unary Plus运算符+(第15.15.3节) 。它指定调用一元运算会导致操作数的一元数值提升(第5.6.1节)。这意味着: * 如果操作数是编译时类型的,,,或,

  • 我在C中实现了一个简单的队列,但是当我试图在退出队列后访问Q. ex时,它会出现分段错误(例如,请参阅int main())。 更准确地说,问题发生在我- 将单个元素排队 把它排出来 使一个或多个元素排队 尝试访问Q.front 然而,程序没有给出分段错误或任何错误,当我- 使多个元素排队 这是我的完整程序-

  • 我有个例外 2018-11-01 21:05:49.122错误31446---[nio-8080-exec-1]O.A.C.C.C.[.[.[/].[dispatcherServlet]:servlet.Service()在路径[]上下文中的servlet[dispatcherServlet]引发异常[请求处理失败;嵌套异常为org.springframework.web.multipart.ma

  • 为什么我会。。。 未捕获的类型错误:string.split 不是一个函数 ...当我跑步时...

  • 我对术语的理解如下 1) 中断 是硬件启动的“通知”,用于调用操作系统运行其处理程序 2) 陷阱 是由软件启动的“通知”,用于调用操作系统以运行其处理程序 3) 故障 是处理器在发生错误但可恢复时引发的异常 4) 中止 是处理器在发生错误但无法恢复时引发的异常 为什么我们称之为而不是? 分割错误 是指程序试图访问操作系统未分配或不允许访问的内存。 我的经验(主要是在测试代码时)是,每当程序抛出