1

ロードされた ada 共有ライブラリを含む C++ アプリケーションを取得して、クラッシュ時にコア ダンプを生成するにはどうすればよいですか?

私はADA共有ライブラリをロードするC++アプリケーションを持っています。ADAコード内でスタックオーバーフローエラーが発生し、コンソール出力とともにプログラムが終了します。

raised STORAGE ERROR

アプリケーションを起動する前に「ulimit -c unlimited」を発行しても、コア ダンプ ファイルが生成されません。

kill SIGSEGV をアプリケーションに送信すると、同じことが起こります。

kill SIGSEGVを ada dll を使用しない別のアプリケーションに送信すると、必要な方法でコア ダンプ ファイルが生成されます。

ここでいくつかの情報を見つけました: http://objectmix.com/ada/301203-gnat-fstack-check-does-work.html

更新しました!Adrien が述べたように、矛盾はありません。- sはスタック制限を設定し、 -cはコア ファイル制限を設定します。

それでも問題は残ります。ada ライブラリのビルド時にフラグを確認したところ、fstack-checkフラグが設定されていなかったため、コア ダンプが生成されるはずです。

まだ試していませんが、少し奇妙に思えます。-fstack-check コンパイラ オプション + GNAT_STACK_LIMIT 変数の設定について言及していますが、同時に、矛盾しているように見える ulimit コマンドを参照しています。「ulimit -c」を設定することが、生成されるコア ダンプを取得する唯一の方法です。クラッシュ時に、これが fstack-check オプションで推測される場合、キャッチ 22 があります。

4

4 に答える 4

7

さて、ほぼ 2 年後 (クリストファーが質問したときと同じ会社でまだ働いています)、再び質問が提起されました。

この問題は、デフォルトで一部の POSIX シグナル (Linux の場合: SIGABRT、SIGFPE、SIGILL、SIGSEGV、および SIGBUS) のシグナル ハンドラーを実装する Ada ランタイムによって引き起こされます。GNAT/linux の場合、シグナル ハンドラーはa-init.cで__gnat_error_handlerと呼ばれ、次のようになります。

static void
__gnat_error_handler (int sig)
{
  struct Exception_Data *exception;
  char *msg;
  static int recurse = 0;
  ...
  switch (sig)
    {
    case SIGSEGV:

      if (recurse)
      {
        exception = &constraint_error;
        msg = "SIGSEGV";
      }
      else
      {
        ...
        msg = "stack overflow (or erroneous memory access)";
        exception = &storage_error;
      }
      break;
     }
    recurse = 0;
    Raise_From_Signal_Handler (exception, msg);
 }

このハンドラーは「プロセス全体」であり、プロセスのどの部分から発生したかに関係なく (Ada/C/C++ でコーディングされているかどうかに関係なく)、トリガーされたシグナルによって呼び出されます。

呼び出されると、ハンドラーは Ada 例外を発生させ、適切な例外ハンドラーを見つけるために Ada ランタイムに任せます。 -runtime はフォールバックしてプロセスを終了し、__gnat_error_handlerからの単純な出力を残すだけです(例: "スタック オーバーフロー (または誤ったメモリ アクセス)")。

http://www2.adacore.com/gap-static/GNAT_Book/html/node25.htm

Ada ランタイムが POSIX シグナルを処理するのを防ぎ、それを Ada 例外に変換するには、次を使用してデフォルトの動作を無効にすることができます。

pragma Interrupt_State (名前 => 値、状態 => SYSTEM | RUNTIME | USER);

例えば。SIGSEGV の処理を​​無効にするには、定義します

Pragma Interrupt_State(SIGSEGV, SYSTEM);

Ada コードで - SIGSEGV が発生したときにシステムのデフォルトの動作がトリガーされ、問題の原因を追跡できるコア ダンプが生成されます。

これは、*NIX プラットフォームで Ada と C/C++ を混在させる場合に注意すべき非常に重要な問題だと思います。これは、問題が Ada コードに起因すると誤解される可能性があるためです (プリントアウトは Ada から生成された例外を示しているため)。 ) 問題の本当の原因が C/C++ コードにある場合...

SIGSEGV の Ada ランタイムのデフォルト処理を無効にすることはおそらく安全ですが (「予想される」エラー処理でこれを使用する正気のプログラマーはいないと思います...まあ、航空ソフトウェアなどで使用される可能性があります。 "本当に悪いことが起こらないようにするには、機能を維持する必要があります..)シグナルのAdaランタイム処理を「オーバーライド」するには、少し注意が必要だと思います。

1 つの問題は、デフォルトで Ada Constraint_Error-exception も発生させる SIGFPE シグナルである可能性があります。このタイプの例外は、Ada コードで「予期される動作」として使用される場合があります。Pragma Interrupt_State で SIGFPE を無効にすると、Ada コードの実行に深刻な影響を与え、「通常の状況」でアプリケーションがクラッシュする可能性があります。一方、C/C++ コードでのゼロによる除算は、Ada 例外処理メカニズムをトリガーします。問題の原因の本当の痕跡なしであなたを残します...

于 2012-10-22T15:11:19.323 に答える
1

これは、 AdaCoreサポートの本当に良い使い方のように思えます。その会社の外に、Gnu Ada のランタイムと C++ の間の相互作用の影響に精通している多くの人々を見つける責任はありません。

Ada コードをデバッグするために、すべてに土壇場の例外ハンドラーを配置して、例外スタックをダンプすることをお勧めします。ほとんどのベンダーは、通常、Ada.Exceptions.Exception_Information と Ada.Exceptions.Exception_Message に基づいて、何らかの方法でこれを実行しています。

于 2010-02-10T18:32:30.917 に答える
0

セキュリティの観点からの議論を見つけました (マルウェアの発見)。基本的に、試すことができる信号は 10 ありますがSIGSEGV、これらはそのうちの 1 つにすぎません。

于 2010-02-11T11:13:07.197 に答える
0

sigaction(SIGSEGV, 0, SIG_DFL);デフォルトの信号動作を復元するために単に呼び出すことができるようです。

于 2010-02-12T10:34:54.990 に答える