さて、ほぼ 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 例外処理メカニズムをトリガーします。問題の原因の本当の痕跡なしであなたを残します...