2016-12-22 8 views
1

次のコードでは、SIGSEGVシグナルを処理し、バインドされた変数を最小化することによって エラー状態を修正しています。私は、シグナルハンドラが復帰するたびに、シグナルが発生している間、命令を再スタートすると思います。シグナルハンドラでは、私は、バインドされた変数を最小限に抑えるが、それでもSIGSEGVを取得し、私はそれはCとPOSIX標準あたり未定義の動作だ間違っエラー状態はまだC言語でSIGSEGVが返ってきている

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

void SIG_segfault_handler(int); 
static int bound = 5800000; 

int main(int argc,char *argv[]) 
{ 
    signal(SIGSEGV,SIG_segfault_handler); 
    puts("This is the driver code for experimenting with signal"); 
    int *array = malloc(50); 
    *(array+ 23) = 78; 
    puts("-------------------------------------------------------------------------------------"); 
    *(array + bound) = 100; 
    printf("Data: %d , %d \n",*(array + 23),*(array + bound)); 

    puts("Initialiazed array with 50 bytes.. \n End of driver code. "); 
    //free(array); 
    return 0; 
} 

void SIG_segfault_handler(int signum) 
{ 
    puts("This is segmentation fault.. cannot continue with the memory operation.. aborting"); 
    puts("Signal SIGSEGV is handled by the program"); 
    puts("Fixing the error conditions.."); 
    bound = 2; 
} 
+1

'puts()'は非同期シグナルセーフではなく、シグナルハンドラから安全に呼び出すことはできません。 **シグナルハンドラから** async-signal-safe関数のみを呼び出すことができます。 http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04 –

+0

シグナルハンドラから戻ったときに命令が再開されるという保証はありません。何かあれば、私はその反対を期待しています。しかし、実際にはどちらにも依存することはできません。 –

+0

結論:このコードは動作しません。修正する方法はありません。セグメンテーション違反を取得することは、生の卵を壊すようなものです。後でピースを拾う方法はありません。 (唯一の解決策は、セグメンテーション違反を持たないこと/最初の場所で卵を壊すことです)。 –

答えて

0

をつもりどこ

わからない無限ループに行きます。 SIGSEGVのシグナルハンドラからのリターンは許可されません。

7.14.1.1 The signal function参照:

信号が発生し、機能にFUNC点は、それが 実装定義されているかどうかの信号の等価(SIG、SIG_DFL)。 が実行されるか、またはインプリメンテーションによって、 信号のセット(少なくともsigを含む)が、現在のシグナル処理が完了するまで発生しないようにします。 SIGILLの場合、 の実装では、何も処理が行われないと定義することもできます。次に、 (* func)(sig)と等価です。実行される。関数 が返ってきたときに、sigの値がSIGFPE、SIGILL、SIGSEGV、または 計算例外に対応する実装定義の値 であれば、その動作は未定義です。それ以外の場合、プログラムは中断された時点で実行を再開します( )。

シグナルハンドラを実行した後、実行はSIGSEGVを引き起こした同じ命令を再開します。つまり、シグナルハンドラから を返した後に、配列がオーバーフローすると(SIGSEGVを引き起こす)、が再びに実行されます。これは無限ループを説明するはずです。

さらに、信号ハンドラからputs()に電話をかけてはいけません。シグナルハンドラ内からのみ非同期シグナルセーフな関数を呼び出すことができます。 async-signal-safe関数のリストについては、POSIX manualを参照してください。

signal()の使用はまた、様々な実装によって提供される異なるセマンティクスのために推奨されません。この理由のために、シグナルハンドラのインストールにはsigaction()を使用することをお勧めします。

関連する問題