2012-10-08 53 views

回答

11

的第一個電話應該返回0;第二個電話應返回-1,並將errno設置爲EBADF

您應該通過將fd設置爲已知的錯誤號碼來防止發生第二個呼叫。一個-1立刻close第一次調用後,隨後進行第二次調用之前檢查fd(而不是進行調用,如果fd-1):

close(fd); 
fd = -1; 
... 
// More code 
... 
if (fd != -1) { 
    close(fd) 
    fd = -1; 
} 

此代碼模式將有助於當你需要對呼叫close,但您不確定該文件是否已打開,或者是否已關閉。通過-1close是無害的(當然你會得到EBADF)。

+0

爲什麼要阻止第二個電話的發生? –

+0

將fd設置爲-1沒有任何作用(它當然不會阻止第二個電話的發生)......它和一個封閉的fd產生EBADF –

+5

@JimBalter將fd設置爲-1將避免偶爾關閉另一個線程剛剛打開的文件的風險 – simonc

7

,除非你是螺紋或做了兩個電話之間的東西,關閉它應該是無害的。然後你可能會最終關閉一個fd,程序中的其他內容已經打開。

線程的方式是相關的,圖書館幾乎總是在背後做奇怪的事情。 Libc將打開查找錯誤消息或其他區域設置相關內容的文件,解析器可以打開配置文件等。如果關閉文件描述符並再次關閉它,在線程環境中,您可以輕鬆地結束文件描述符已被庫重用,並將其關閉在背後。

+0

+1在線程環境中提及可能的問題。 – alk

+0

關閉的* first *調用可能會從另一個線程關閉fd。兩個關閉與這個問題無關。線程的唯一途徑是與此相關的是,第二個可能不會失敗,畢竟如果該fd被重新打開,但這沒什麼意思......如果你不同步你的線程,它們可能會發生各種不好的事情。 –

+2

由open()返回的值由操作系統回收。所以如果線程A調用了'open()'並且得到了fd = 3,那麼'close()'就是了。然後,在線程A第二次調用close()之前,線程B成功調用了'open()',並且再次獲得了fd = 3。那麼線程A調用的第二個'close()'會做什麼? – alk

1

如果該值PF FD仍然是第二個電話會返回一個錯誤的fd是無效的(EBADF - 作爲dasblinkenlight指出的)相同

想想做財產以後的likg

if fd != -1) 
{ 
    close (fd); 
    fd = -1; 
} 
+1

這類事情是毫無意義的,因爲close(fd)不是未定義的,或者在fd已經關閉時以任何方式危險... close(fd)和close(-1)完全一樣。將fd設置爲-1的唯一原因是確保它不是有效的打開文件描述符,例如0. –

+0

好的,人們已經注意到文件描述符可能已在另一個線程中重新打開,因此設置fd = -1是很好的做法。但是'fd!= -1'測試不是絕對必要的......沒有它的效果是一樣的。 –

+1

我確實同意你不需要測試-1。甚至更多:在調試構建中,我會忽略它,並記錄錯誤'close()'將返回,然後指向我創建的混亂,導致嘗試關閉文件兩次...... ;-) @ Jim同意 – alk

3

第二次調用將失敗Errno: EBADF當 ,因爲屆時,fd不是活動文件描述符。

它應該完全沒有影響執行。但是,如果任何錯誤編號由第一次關閉設置,則會丟失,因此您不應該關閉文件描述符兩次。

+0

啊,這個答案其實說的是有效的東西! +1 –

4

關閉相同 FD兩次應該是非致命的,正如其他人所指出的,但像他這樣

close(fd); 
/* ... */ 
newfd = open(....); 
/* ... */ 
close(fd); 

的代碼提防在第二次接近,你不能肯定是否fd實際上是與newfd一樣!只要您嘗試使用newfd,就會導致崩潰。

因此(如果兩個close調用之間存在代碼),這樣做並不安全。總是close文件描述符只有一次。始終free緩衝一次。