0

C で非常に単純なプログラム実行タイマーを作成しています。以下にサンプル コードを示します。問題は、プログラムを+ (つまりシグナル)で終了するときに、 からfflush(NULL)すべてをフラッシュしないことです。メッセージの後にまだ時々表示されるのですが、なぜだろうと思います。"Hello World\n"stdoutCtrlCSIGINTEstimated running time...

タイマー.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);
}

タイマー.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;
}
4

1 に答える 1

3

プログラムが未定義の動作を呼び出します。fflush()シグナル ハンドラ内で呼び出すことはできません。一般に、シグナル ハンドラ内で IO ライブラリ関数を呼び出すことはお勧めできません。

厳密に準拠したプログラムは、C 標準ライブラリ関数abort()_Exit()quick_exit()、およびsignal()をシグナル ハンドラ内からのみ呼び出すことができます。

つまり、fflush()非同期セーフではないため、これを実行しようとしないでください。

詳細については、次の質問を参照してください: I need a list of Async-Signal-Safe Functions from glibc

その質問は、可能な回避策へのリンクを示しています。

于 2014-01-11T15:06:32.857 に答える