C++ での例外の処理には、言語レベルでの暗黙の制限がいくつかありますが、場合によってはそれらを回避できる場合があります。例外を利用するさまざまな方法を学ぶことで、より信頼性の高いアプリケーションを作成できます。例外ソース情報の保持 C++ では、ハンドラー内で例外がキャッチされると、例外ソースに関する情報は不明になります。例外の特定のソースは、例外をより適切に処理するための多くの重要な情報を提供したり、後で分析するためにエラー ログに追加できる情報を提供したりすることができます。 この問題を解決するには、throw ステートメント中に例外オブジェクトのコンストラクターでスタック トレースを生成します。 ExceptionTracer は、この動作を示すクラスです。 リスト 1. 例外オブジェクト コンストラクターでのスタック トレースの生成 // サンプル プログラム:
// コンパイラー: gcc 3.2.3 20030502
// linux: Red Hat #include
#include < ; signal.h> #include
#include
{
public:
ExceptionTracer()
{
void * array[25];
int nSize = backtrace (array, 25);
char ** シンボル = backtrace_symbols(array, nSize);
for (int i = 0; i < nSize; i++)
{
cout <<シンボル[ i] << endl;
} free(symbols);
}
}; ガバナンス シグナル Linux カーネルにシグナルを発行させる迷惑なアクションを実行するたびに、シグナルを処理する必要があります。通常、シグナル ハンドラーはいくつかの重要なリソースを解放し、アプリケーションを終了します。この場合、スタック上のすべてのオブジェクト インスタンスは破壊されていない状態です。一方、これらの信号が C++ 例外に変換される場合は、コンストラクターを適切に呼び出して、複数の層の catch ブロックを配置して、これらの信号をより適切に処理できます。 リスト 2 で定義されている SignalExceptionClass は、カーネルによって通知される可能性のある C++ 例外を表すための抽象化を提供します。 SignalTranslator は、SignalExceptionClass に基づくテンプレート クラスで、通常は C++ 例外への変換を実装するために使用されます。アクティブなプロセスのシグナルを処理できるシグナル ハンドラーは常に 1 つだけです。したがって、SignalTranslator はシングルトン設計パターンを採用しています。全体的な概念は、SIGSEGV の SegmentationFault クラスと SIGFPE の FloatingPointException クラスを通じて示されます。 リスト 2. シグナルを例外に変換する
template
{
private:
class SingleTonTranslator
{
public:
SingleTonTranslator()
{
signal( SignalExceptionClass ::GetSignalNumber(),
SignalHandler);
} static void SignalHandler(int)
{
throw SignalExceptionClass();
}
}; public:
SignalTranslator()
{
静的SingleTonTranslator s_objTranslator;
}
} // SIGSEGV
class SegmentationFault の例: public ExceptionTracer, public
例外
{
public:
static int GetSignalNumber() {return SIGSEGV ; }
} ; SignalTranslator
} ; SignalTranslator
g_objFloatingPointExceptionTranslator; コンストラクターとデストラクターでの例外の管理 すべての ANSI C++ がグローバル (静的グローバル) 変数の構築中に例外をキャッチすることは不可能です。したがって、ANSI C++ では、インスタンスがグローバル インスタンス (静的グローバル インスタンス) として定義されている可能性があるクラスのコンストラクターおよびデストラクターで例外をスローすることはお勧めしません。つまり、コンストラクターとデストラクターが例外をスローする可能性があるクラスには、グローバル (静的グローバル) インスタンスを決して定義しないでください。ただし、特定のコンパイラと特定のシステムを想定すると、そうすることができる可能性があり、幸いなことに、Linux 上の GCC ではまさにこれが当てはまります。 これは、同じくシングルトン設計パターンを採用する ExceptionHandler クラスを使用して実証できます。そのコンストラクターは、キャッチされなかったハンドラーを登録します。アクティブなプロセスを処理できる捕捉されないハンドラーは一度に 1 つだけであるため、コンストラクターは 1 回だけ呼び出す必要があり、したがってシングルトン パターンとなります。 ExceptionHandler のグローバル (静的グローバル) インスタンスは、問題の実際のグローバル (静的グローバル) 変数を定義する前に定義する必要があります。 リスト 3. コンストラクターでの例外処理 class ExceptionHandler
{
private:
class SingleTonHandler
{
public:
SingleTonHandler()
{
set_terminate(Handler);
} static void Handler()
{
// グローバル変数の構築/破壊による例外 try
{
// re-throw throw;
}
catch (SegmentationFault &)
{
コート << “セグメンテーション障害” << endl;
}
catch (FloatingPointException &)
{
cout << “FloatingPointException” << endl;
}
catch (...)
{
cout << 「不明な例外」 << endl;
} //これがコアアクティビティを実行するスレッドの場合
abort();
//そうでない場合、これがリクエストのサービスに使用されるスレッドの場合
// pthread_exit();
}
} ; public:
ExceptionHandler()
{
static SingleTonHandler s_objHandler;
}
}; //////////////////////////////////////////////// //////////////////////// クラス A
{
public:
A()
{
//int i = 0, j = 1/i;
*(int *)0 = 0;
}
}; // グローバル変数を定義する前に、ExceptionHandler オブジェクトのダミー インスタンス
// を定義して、
// ExceptionHandler::SingleTonHandler::SingleTonHandler() が呼び出されることを確認します
ExceptionHandler g_objExceptionHandler;
A g_a ; //////////////////////////////////////////////// //////////////////////// int main(int argc, char* argv[])
{
return 0;
} 处理多線程多くの場合、プログラム内の一部の例外が捕捉されず、これによりプロセスが中止されることがよくあります。そのプロセスには、一部のプロセスがコア アプリケーションとして実行され、残りのプロセスが外部からのサービスを提供することが含まれます。これは、アプリケーション プログラムに不正なリクエストを送信することによってサービス攻撃の拒否を助長する可能性があるため、歓迎されない可能性があります。 、未捕捉処理プログラムは、要求の定期中止用であるか、要求ラインプロセスの退出用であるかを決定できます。クリア 3 中の ExceptionHandler::SingleTonHandler::Handler() 関数の最終処理プログラムが表示されます。 ++编程次のタスクをより適切に実行するためにモードを設定します。 · 異常な発生時に異常なソースを追跡します。 · 信号を内部コア プログラムから C++ に変換します。
· 多回線プロセス中の常套処理。