我讀「UNIX網絡編程:套接字聯網API」和示例代碼,他們有一個錯誤處理功能,其中包含以下行:爲什麼在寫stderr之前需要在stdout上使用fflush?
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
fflush(stderr);
凡buf將包含一個錯誤的描述。我不明白爲什麼fflush在第一行的標準輸出上使用,以及爲什麼評論解釋了它的使用原因。
我讀「UNIX網絡編程:套接字聯網API」和示例代碼,他們有一個錯誤處理功能,其中包含以下行:爲什麼在寫stderr之前需要在stdout上使用fflush?
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
fflush(stderr);
凡buf將包含一個錯誤的描述。我不明白爲什麼fflush在第一行的標準輸出上使用,以及爲什麼評論解釋了它的使用原因。
這是因爲緩衝。 Stdout and stderr are usually buffered differently。標準輸出爲通常爲行緩衝,意味着它將不會顯示輸出,直到它看到一個換行符。 Stderr是通常是無緩衝,並會立即打印,思維是你應該看到錯誤信息pronto。
但他們都去同一個地方,終端。這就是/* in case stdout and stderr are the same */
的含義。他們通常是。但是因爲它們的緩衝區不同,這可能會導致它們無序顯示。
請考慮這段代碼。請注意缺乏換行符。
#include <stdio.h>
int main() {
fprintf(stdout, "This is to stdout. ");
fprintf(stderr, "This is to stderr. ");
fprintf(stdout, "This is also to stdout. ");
}
你所期望的輸出是:
This is to stdout. This is to stderr. This is also to stdout.
但事實並非如此。這是無序的。
$ ./test
This is to stderr. This is to stdout. This is also to stdout.
輸出到stderr立即顯示,它是無緩衝的。雖然stdout必須等待直到標準輸出緩衝區被換行符刷新。沒有換行符,所以程序退出時會刷新。
通過在使用標準錯誤之前清除標準輸出,您可以確保輸出按照正確的順序進行,無論緩衝如何。
#include <stdio.h>
#include <unistd.h>
int main() {
fprintf(stdout, "This is to stdout. ");
fflush(stdout);
fprintf(stderr, "This is to stderr. ");
fprintf(stdout, "This is also to stdout. ");
}
$ ./test
This is to stdout. This is to stderr. This is also to stdout.
這確保錯誤消息以正確的順序與正常消息一起出現。這可以避免混淆哪些錯誤信息適用於程序的哪一部分。
如果stdout和stderr指向同一個文件,則必須確保首先寫入stdout緩衝區中的任何內容。
你的第二個例子是錯誤的; '這也是stdout.'和'這是stdout.'應該被切換。 – Qix
如果'stderr'是反特徵緩衝的,那麼類似的問題將會發生,而這個答案並不能解決這個問題。在寫作之前,用筆尖沖洗另一個。或者使用良好的禮儀和[沖洗完成後] – chux
@Qix謝謝。我最初混淆了代碼中的文件句柄。 – Schwern