对同一个函数中的一个fd进行多次关闭调用是否重要?

j10*_*j10 15 c file-io file

我只是想知道在fd上连续两次关闭的行为是什么.

例如-

close(fd);
close(fd);
Run Code Online (Sandbox Code Playgroud)

[fd是一个int]

das*_*ght 15

第一个电话应该返回0; 第二个调用应该返回-1,并设置errnoEBADF.

您应该通过设置fd为已知的错误号码来阻止第二次呼叫发生,例如-1在第一次呼叫之后立即进行close,fd然后在进行第二次呼叫之前进行检查(如果fd是,则不进行呼叫-1):

close(fd);
fd = -1;
...
// More code
...
if (fd != -1) {
    close(fd)
    fd = -1;
}
Run Code Online (Sandbox Code Playgroud)

当您需要close从多个位置进行调用时,此代码模式将有所帮助,但您不确定该文件是否已打开,或者该文件是否已关闭.传递-1close是无害的(你会得到一个EBADF,当然).

  • @JimBalter将fd设置为-1可避免偶尔关闭另一个线程刚刚打开的文件的风险. (8认同)
  • 这个例子很危险.我已经探索过的所有操作系统(BSD,Linux,Solaris)都会关闭文件描述符,即使关闭的内部部分失败也是如此(由于像AFS这样的文件系统在关闭语义上同步,你可以添加关闭失败)写入和关闭之间丢失凭据).执行第二次关闭将关闭可能已被其他人重用的文件描述符.关闭时不要聪明,只关闭一次,并通知用户出现问题(这是emacs的作用). (4认同)

Art*_*Art 8

它应该是无害的,除非你在两次关闭调用之间进行了线程化或做某事.那么你最终可能会关闭一个fd,程序中的其他内容已经打开了.

线程的相关方式是图书馆几乎总是在你背后做一些奇怪的事情.Libc将打开文件以查找错误消息或其他依赖于区域设置的东西,解析器可以打开配置文件等.如果关闭文件描述符并再次关闭它,在线程环境中您很容易就会遇到文件的情况描述符已被库重用,您可以在它后面关闭它.

  • "open()"返回的值由操作系统回收.因此,如果线程A调用`open()`并得到fd = 3,那么`close()就是它.然后在线程A第二次调用`close()`之前,线程B成功调用`open()`并再次获得fd = 3.那么线程A调用的第二个`close()`会怎样呢? (2认同)
  • 为了增加宇宙的乐趣,我和一位同事花了 5 个小时调试一个问题,结果证明是线程服务器中的双重关闭。有时现实比你想象的更快地追上理论论证。 (2认同)

Ani*_*han 5

第二次调用将失败,Errno: EBADF因为到那时,fd 不是活动的文件描述符。

它应该对执行没有任何影响。但是,如果第一次关闭时设置了任何错误编号,则该编号将丢失,因此您不应两次关闭文件描述符。


Gui*_*ido 5

如同其他人所指出的那样,关闭相同的 fd两次应该是非致命的,但要小心这样的代码

close(fd);
/* ... */
newfd = open(....);
/* ... */
close(fd);
Run Code Online (Sandbox Code Playgroud)

到第二次结束时,你不能确定它fd是否真的一样newfd!每当您尝试使用时,这都会导致崩溃newfd.

所以(如果两个close调用之间都有代码),这样做是不安全的.始终只close对文件描述符进行一次.始终只free缓冲一次.