看板 C_and_CPP 關於我們 聯絡資訊
以下是在 VS2008 用單步執行跳出來的 code 先來看一下 fflush 的部份實作碼(其他不重要): int __cdecl fflush (REG1 FILE *stream) { __try { rc = _fflush_nolock(stream); } } 再往下追,就會看到: int __cdecl _fflush_nolock (REG1 FILE *str) { if (_flush(str) != 0) { /* _flush failed, don't attempt to commit */ return(EOF); } } fflush 看到這裡就夠了,因為接下來看 printf 有這麼一行: int __cdecl printf (const char *format, ...) { _ftbuf(buffing, stdout); } 再往下追,可以看到: void __cdecl _ftbuf (int flag, FILE *str) { REG1 FILE * stream = str; _flush(stream); } 雖然挖到的 code 大部份我都看不懂 XD 不過應該可以得到:「 printf 底層會呼叫 fflush 底層」這樣的結論 因此,每次呼叫 printf,效果就跟 printf + fflush(stdout); 相同 對了,我抓出來的 code 都不在 branch 裡,是正常情況一定會執行到的~ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.117.171.46 ※ 編輯: james732 來自: 140.117.171.46 (09/16 23:37)
loveflames:在程式開頭加上setbuf(stdout,buf);也會馬上跑flush? 09/16 23:43
void __cdecl setbuf (FILE *stream, char *buffer) { if (buffer == NULL) setvbuf(stream, NULL, _IONBF, 0); else setvbuf(stream, buffer, _IOFBF, BUFSIZ); } int __cdecl setvbuf (FILE *str, char *buffer, int type, size_t size) { REG1 FILE *stream; int retval=0; /* assume good return */ stream = str; _lock_str(stream); __try { _flush(stream); _freebuf(stream); (以上仍然略掉了部份程式碼) 看來 setbuf 是一定會跑 _flush 的 ※ 編輯: james732 來自: 140.117.171.46 (09/17 00:02)
loveflames:啊啊,我的意思是程式開頭用setbuf,然後輸出到stdout 09/17 00:32
loveflames:最後輸出到stderr,看前面的stdout是不是馬上flush 09/17 00:33
原來是這樣 XDD 我誤解了 int main(void) { char buf[1024]; setbuf(stdout, buf); printf("Hello"); fprintf(stderr, "Oh!"); } 測試的結果是... ---- Oh! ---- 並沒有馬上被 fflush 出去 我又去挖了一下 code, 發現了奇怪的現象: int __cdecl printf (const char *format, ...) { va_list arglist; int buffing; int retval; va_start(arglist, format); _lock_str2(1, stdout); __try { buffing = _stbuf(stdout); /* 如果沒有 setbuf,那麼這個 buffing 就是 1, 反之為 0 */ retval = _output_l(stdout,format,NULL,arglist); _ftbuf(buffing, stdout); } 再把 _ftbuf 看仔細一點: void __cdecl _ftbuf (int flag, FILE *str) { REG1 FILE *stream = str; if (flag) { /* 如果沒有 setbuf,那麼這個 flag 就是 1, 反之為 0 */ if (stream->_flag & _IOFLRTN) { /* Flush the stream and tear down temp buffering. */ _flush(stream); stream->_flag &= ~(_IOYOURBUF | _IOFLRTN); stream->_bufsiz = 0; stream->_base = stream->_ptr = NULL; } } } 在關鍵的 _stbuf 裡,有段奇怪的程式碼: /* Make sure the stream is not already buffered. */ if (anybuf(stream)) return(0); 如果有 setbuf, 那麼這裡就會直接 return 了 不過那個 anybuf 似乎不是個真的 function,按 F11 跳不進去,無法再追 orz 我前文說「這些 _flush 一定會被執行」倒是個很大的失誤,真是不好意思 XD ※ 編輯: james732 來自: 140.117.171.46 (09/17 00:57)
loveflames:Hello沒印出來對吧,因為最後的fflush()是由exit()呼叫 09/17 10:59
loveflames:的,buf那時已經沒了 09/17 11:00
james732:覺得這裡的機制好像比想像中的還要複雜些 XD 09/17 11:07