2

自分のアドレス空間を調べるプログラムを書いています。

具体的には、malloc されたすべてのデータ ブロックに関心があります。それらのリストを取得するためのシステム コールがあれば、それは素晴らしいことです (私のアプリケーションでは、LD_PRELOAD、-wrap、または追加のコマンド ライン オプションは使用できません)。これを行う方法がある場合は、以下に述べた問題に対する回答以上に、それを聞きたいと思います。

これに代わって、私の現在のアプローチは、すべてを逆参照して周りを見回すことです。明らかに、すべての可能なポインターのセットは、発生するのを待っているセグメンテーション違反の地雷原であるため、シグナルハンドラーを登録し、setjmp/longjmp を使用してみました (ハンドラーが何もしないようにしてセグメンテーション違反を単に無視すると、ハンドラーがに戻るため、無限ループになります)フォルト命令)。いくつかのサンプルコードは次のようになります:

static jmp_buf buf;
void handler(int i) {
    printf("    Segfaulted!\n");
    longjmp(buf,-1);
}
void segfault(void) {
    int* x = 0x0;
    int y = *x;
}
void test_function(void) {
    signal(11,handler);
    while (1) {
        if (setjmp(buf)==0) {
            printf("Segfaulting:\n");
            segfault();
        }
        else {
            printf("Recovered and not segfaulting!\n");
        }
        printf("\n");
    }
}

出力は次のとおりです。

    Segfaulting:
        Segfaulted!
    Recovered and not segfaulting!

    Segfaulting:
    Segmentation fault

そのため、ハンドラーは 2 回目は機能しませんでした。これがなぜなのかはわかりませんが、元の信号がクリアされていないことに関係があると推測しました。私はそれを行う方法がわかりません。

余談ですが、最初に sigsetjmp/siglongjmp を試してみたのですが、なぜか setjmp.h に定義されていませんでした。追加のコンパイル フラグを渡す必要があるという漠然とした雰囲気がありましたが、以前と同様に、このアプリケーションでは許可されていません。

使用されているシステムは Ubuntu Linux 10.04 x86-64 であり、どのソリューションも移植可能である必要はありません。

ありがとう!
イアン[

編集: ハンドラーの sigrelse はシグナルをクリアし、問題を効果的に修正します。質問は、提起された他の問題に関するものです。より良い方法 (つまり、malloc のブロックを取得する方法) はありますか? sigsetjmp/siglongjmp はどうなっていますか? なぜ信号をリセットする必要があるのですか?]

4

2 に答える 2

2

signal()レガシー インターフェイスであり、OS によっては、呼び出された後にシグナル ハンドラを再登録する場合と再登録しない場合があります。signal()ハンドラーの最後のアクションとしてシグナル ハンドラーをリセットするには、別の呼び出しを発行する必要がある場合があります。を参照してくださいman 2 signal

sigaction()は、明確に定義された移植可能な動作を備えているため、シグナル ハンドラーを設定するための推奨されるメカニズムです。

于 2012-04-25T00:19:07.647 に答える
1

のシグナルハンドラSIGSEGVが呼び出されると、SIGSEGVシグナルは によってマスクされたかのようにマスクされsigprocmaskます。これは、どの信号にも当てはまります。通常、シグナルハンドラーから戻るとマスクが解除されますが、戻っていないため、それは決して起こりません。考えられる解決策はいくつかあります。

  • sigprocmaskの前または後に呼び出しlongjmpて、自分でマスクを解除できます。
  • シグナルハンドラーをsigaction(とにかくそれを行うための推奨される方法)でインストールし、SA_NODEFERフラグを使用してマスクされないようにすることができます。
  • sigsetjmpおよび関数を使用できます。これらのsiglongjmp関数は、シグナル マスクの保存と復元を担当します。
于 2012-04-25T01:09:59.660 に答える