2015-08-14 44 views
2

我正試圖集成一個小型的Win32 C++程序,它從stdin讀取並將解碼結果(~128千字節)寫入輸出流。我應該總是明確地關閉stdout嗎?

我讀整個輸入到緩衝用

while (std::cin.get(c)) { } 

我寫整個輸出到標準輸出後。

當我從命令行運行應用程序時,一切工作正常,例如test.exe <input.bin> output.bin,但是這個小應用程序應該從Python運行。

我想到了Python subprocess.communicate應該被使用,文檔說:

與互動的過程:將數據發送至標準輸入。從stdout和 stderr中讀取數據,直到達到文件結束。等待進程終止。

因此communicate()將等待我的應用程序完成前等待文件結束 - 應用程序退出時是否應該發生EOF?或者我應該明確做fclose(stderr)和fclose(stdout)?

+4

您不應該明確地釋放您未明確獲取的任何資源,除非您有特定的文檔說明否則。如果不堅持這一點,則難以解決問題。 – mah

+0

現在我明白了這一點 - 子進程獲取自己的句柄/描述符,用於至少在子進程終止時關閉的管道的另一端。 –

+1

無關聯:模擬'test.exe < input.bin > output.bin' shell命令,可以使用'subprocess.check_call('test',stdin = open('input.bin'),stdout = open('stdout.bin', 'w'))'即你不需要'.communicate()'。 – jfs

回答

8

不要關閉標準輸出

在一般情況下,這其實是錯誤的,因爲它可以註冊atexit()一個函數,它試圖寫入標準輸出,並且如果stdout被關閉,這將打破。

當進程終止時,操作系統自動關閉所有句柄。這包括標準輸出,因此您不負責手動關閉它。

(技術上,C++運行時將normally嘗試刷新並關閉所有的C++流之前的OS甚至有機會參與,但操作系統絕對必須關閉任何手柄,其運行時,爲whateverreason,失誤。)

在特殊情況下,關閉標準流(例如,守護進程時)可能很有用,但應該非常小心。將空設備重定向到空設備通常是一個好主意(Unix上的/dev/null,Windows上的nul),以便期望與這些流進行交互的代碼仍然可以工作。在Unix上,這是通過freopen(3)完成的; Windows有an equivalent function,但它是POSIX API的一部分,可能無法與標準Windows I/O配合使用。

+0

我會稍微修改一下 - 如果你有特定的原因這樣做,關閉標準輸出可能是可以接受的,即你需要在沒有實際退出的情況下發出數據結束的信號。當然,你必須小心確保程序在這樣做之後不會使用stdout。 –

+0

@HarryJohnston:在某些特殊情況下這可能是合理的,但您需要仔細評估您可能使用的任何庫或其他代碼。例如,在某些系統上,當某個進程通過信號死亡(「Terminated」,「Killed」,「Segmentation Fault」等)時,您可能會得到輸出,而且我不確定是否需要功能stdout/stderr,或者如果沒有標準輸出則表現如何。 – Kevin

+0

你可以關閉然後用/ dev/null重新打開3個std句柄,這樣0,1,2路由爲null,就像我們如何守護進程一樣。 –

相關問題