作者loveflames (咕啾咕啾魔法陣)
看板C_and_CPP
標題[心得] stdout & stderr & fflush()
時間Sat Nov 20 07:00:45 2010
標題不知該打什麼,最近正好在跟人討論這個,
發現16192那篇有些東西講錯,所以把重點重新整理了一下,
以下物件都是指cout、clog、cerr
1.該物件所用的stream是否按照規定分配buffer
全緩衝:buffer滿了才執行fflush()
行緩衝:buffer滿了or碰到換行字元才執行fflush()
無緩衝:不管buffer有沒有滿都執行fflush()
cout使用stdout stream
cerr跟clog使用stderr stream
console下
標準 windows linux
stdout|行/無緩衝|全緩衝 |行緩衝 |
stderr|行/無緩衝|全緩衝 |無緩衝 |
非console(即重定向)
標準 windows linux
stdout|全緩衝 |全緩衝 |全緩衝 |
stderr|行/無緩衝|全緩衝 |無緩衝 |
以上是預設值,有一點要釐清,全/行/無緩衝只是該stream的特性,
與它有沒有buffer並沒有關係,網路上的解釋幾乎都把這兩個混在一起講,
拿windows來說,乍看之下會等到buffer滿才輸出,但實際上是直接輸出,
因為沒有分配buffer,如果把屬性是全/行緩衝且分配buffer的stream的flag,
改成_IONBF,也會直接執行fflush()
如果要分配buffer給stream,可以用setbuf()和setvbuf(),
用前者時要注意,一但用它分配buffer後,原本的緩衝特性會消失,
舉例來說,setbuf(stdout,buf)會變為全緩衝,
setbuf(stdout,0)會變為無緩衝,且buffer不能是local變數,
因為最後一次fflush()是在exit()裡執行,那時local變數已經被釋放
註:windows下的_IOLBF,作用等同於_IOFBF,也就是windows實際上沒有行緩衝
2.該物件是否按照規定設置ios::unitbuf
如果有設ios::unitbuf,就直接執行fflush(),
即使底下stream設成全緩衝跟分配buffer也一樣,
除非手動設定,否則只有cerr才有設ios::unitbuf
如果要修改物件的ios::unitbuf,可用setf()或unsetf()設定
3.該物件的是否按照規定綁定別的物件
標準 windows linux
clog.tie()|null |&cout|null |
cerr.tie()|&cout|&cout|&cout|
cout.tie()|null |null |null |
如果有綁別的物件,當自己被寫入時,
不管自己能不能馬上跑fflush(),
都會先讓被綁定的物件執行fflush()
如果要修改綁定的物件,就用tie()來設,傳0代表不綁定
下列網站也寫cin、cerr綁定cout(C++11)
http://www.cplusplus.com/reference/iostream/ios/tie/
4.換行字元跟endl
前者只能讓行緩衝的stream跑fflush(),
後者則強迫cout、cerr、clog跑fflush()
5.如果一直到main()結束都沒有跑fflush()
那麼stdout會先輸出,接著才是stderr
6.main()結束後,不可再用cout、cerr、clog來輸出
首先來看exit()的標準流程
A.銷毀thread變數
B.銷毀global變數/銷毀函式裡的static變數/執行atexit註冊函式
C.讓所有的C stream執行fflush(),接著關閉它們
D.砍掉暫存檔
E.歸還控制權給OS
在執行dtor/atexit註冊函式時,無法保證cout、cerr、clog這些物件還在,
雖然標準是有規定這些物件最慢銷毀
總結:
沒分配buffer、屬性為無緩衝、ios::unitbuf不為0、buffer已滿
、行緩衝碰到'\n'、讓物件使用endl/flush/flush(),綁定自己的物件被寫入
以上只要有一個成立就會跑fflush()
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 111.252.64.44
→ tinlans:...局...局...局部...局部變量? 11/20 07:41
→ loveflames:local variable啦,腦袋還沒從大陸的用語轉過來 11/20 07:42
→ loveflames:沒人回,看來似乎是太基本了(汗) 11/22 10:14
推 nowar100:心得不錯啊 不過通常我都懶得管有沒有緩衝 XD 11/22 11:20
→ loveflames:用fork()時,前面如果先設成unbuffered就省事多了 11/22 14:45
→ loveme00835:我也沒在管緩衝這部份的問題 XD 11/22 17:50
※ 編輯: loveflames 來自: 220.130.247.105 (03/21 10:55)