2014-01-11 66 views
0

我在C中創建了一個非常簡單的程序執行計時器。我將在下面提供示例代碼。問題是fflush(NULL)在用Ctrl + C(即SIGINT信號)結束程序時不會沖洗來自stdout的每個"Hello World\n"。他們仍然在Estimated running time...消息之後出現,我不知道爲什麼。fflush()無法正常刷新

/timer.c裏

#include <signal.h> 
#include <time.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <stdio.h> 

#define _TIMER 
#include "timer.h" 

static clock_t startTime; 

int installTimer(void) 
{ 
    errno = 0; 
    if (signal(SIGINT, signalHandler) == SIG_ERR || 
     signal(SIGTERM, signalHandler) == SIG_ERR || 
     signal(SIGABRT, signalHandler) == SIG_ERR) 
     return 1; 
    if (atexit(displayTimer)) 
     return 1; 
    if ((startTime = clock()) == -1) 
     return 1; 
    return 0; 
} 

static void displayTimer() 
{ 
    clock_t endTime; 
    if ((endTime = clock()) == -1) 
     printf("ERROR: clock() failed.\n"); 
    else 
     printf("Estimated running time: %.4fs\n", (endTime - startTime)/(double) CLOCKS_PER_SEC); 
} 

static void signalHandler(int signal) 
{ 
    fflush(NULL); 
    exit(EXIT_FAILURE); 
} 

Timer.h:

int installTimer(void); 

#ifdef _TIMER 
    static void displayTimer(void); 
    static void signalHandler(int); 
#endif 

timerTest.c

#include <stdio.h> 
#include "timer.h" 

int main(void) 
{ 
    if (installTimer()) 
    { 
     printf("ERROR: installTimer() failed.\n"); 
     return 1; 
    } 
    int i; 
    for (i = 0; i < 300000; ++i) 
     printf("Hello World!\n"); 
    return 0; 
} 

回答

3

你的程序調用未定義的行爲。信號處理程序內部不能調用fflush()。在信號處理程序中調用IO庫函數通常是一個糟糕的主意。

嚴格符合的程序只能從信號處理程序中調用C標準庫函數abort()_Exit(),quick_exit()signal()

換句話說,fflush()不是異步安全的,所以請不要嘗試這樣做。

有關進一步詳情,請參閱這個問題:I need a list of Async-Signal-Safe Functions from glibc

這個問題點與可能的解決方法的鏈接。

+0

謝謝,但是您是否也有Windows的異步信號安全函數列表? – Jori

+0

另外,如果我理解正確,那麼在程序結束時就沒有辦法打印估計的時間信息,因爲'fflush()'不是異步信號安全的(儘管我可以用'write'替換'printf'如果這在Windows上是安全的)。 – Jori

+0

嗯,我會在這裏誠實:對於Windows,我不知道。您可以安裝Windows POSIX實現,然後使用POSIX列表實現異步安全功能。否則,我建議閱讀具體的文檔。我通常不會爲Windows開發,所以我真的走出了這個世界。至於你的第二個問題,是的,你必須用'write'這樣的安全調用來完成。 –