1. 例外設計 における大罪 和田 卓人 (a.k.a id:t-wada or @t_wada) Jun 27, 2012 @ java-ja 12年6月28日木曜日 2. 自己紹介 名前: 和田 卓人 (わだ たくと) ブログ: http://d.hatena.ne.jp/t-wada メール: takuto.wada@gmail.com Twitter: http://twitter.com/t_wada タワーズ・クエスト株式会社 取締役社長 12年6月28日木曜日
しばらくカーネル空間で例外ハンドラをいじって遊んでいたのだけど、ユーザー空間でも似たような遊びができる気がしたので下調べのメモ。常に以下のフローをたどるわけではなく、あくまで発生した例外がユーザー空間に伝播するときのフロー。x86はWindows XP SP3、x64は7を見ている。 何らかの理由で割込みもしくは例外が発生する。 ハードウェアによりIDTが参照され、発生した例外の番号に対応する例外ハンドラ*1にEipが設定される。 例外ハンドラのアクションはアーキテクチャ別。 x64 例外ハンドラはKiExceptionDispatchを呼び出す KiExceptionDispatchはKiDispatchExceptionを呼び出す KiDispatchExceptionはKTRAP_FRAME.Ripに大域変数KeUserExceptionDispatcherをセットする mov ra
「れいがい!」、「REIGAI REIGAIせよ!」、「そろそろれいがいさんへの思いを適当にまとめる」も参照のこと。 assert/エラー/例外の区別。 意味論上、本質的な違いはない。現状の実装などの都合で使い分けるもの。 問題の通知に使用される場合の signal やモナド*1等も意味論上、本質的な違いはない。 本来これらは同じような構文で記述できるべき。 assert/エラー/例外の使い分け。 なにか問題が起きた場合は基本的に例外を投げる。 リリース版ではそもそも発生することがあってはならない類の問題については assert を使用する。 パフォーマンスが問題にならない場合は assert とともに例外やエラーを併用することを推奨。 問題が起きても無視してよいものあるいは例外ではパフォーマンスや呼び出し側の実装の都合が悪い場合にはエラーする。 assert/エラー/例外の役割。 問題が
Code Project という有名サイトに、VC++の例外処理方法に関する記事があります (http://www.codeproject.com/cpp/Exceptionhandler.asp) が、そこにg++の例外処理方法を解説したコメントがありました。 ざっくりと次のような事を言っています(翻訳してるわけではないので詳しくは英文読んでください)。 g++は、VC++とはちょっと違うやりかたで例外処理を実装している。g++の場合、実際に例外がthrowされない限りは、try/throw/catchを使ったコードを書いてもランタイムのコストはかからない。 foo()がbar()を呼んでいて、bar()が例外を投げるとせよ。このとき、foo()はスタックに戻りアドレス*1を置いてからbar()を呼ぶ。この戻りアドレスを仮にXとする。 このときコンパイラは、 (X, 掃除コードのアドレス
下手なコードを書くプログラマーの中には、 「例外をキャッチさえすればプログラムがクラッシュしない」 といわんばかりに、 あちらこちら例外を catch しては、その問題を闇に葬り去るひとがいます。 特に重要なところでは、問題が起きたとき、エラーメッセージとしてそれを知らせてくれるか、 ログに記録するなりすると良いのですが、そうなっていないときもあります。 運用環境で、Visual Studio が無いような状況でそんなことが起きたときにどうしたらよいか。 調査テクニックを紹介します。 実際に動かして、Exception オブジェクトのメッセージを見る ここで使うサンプルプログラムはこんなものです。 ボタンが二つあり、左の Test1 、右の Test2 を押すとそれぞれ、下の button1_click 及び button2_click が実行されます。 button1_click 、 b
try ... catch() や __try ... __except() を使用できれば、そちらが簡単。 #include <stdio.h> #include <windows.h> LONG CALLBACK ExceptionHandler(EXCEPTION_POINTERS *ExceptionInfo) { printf("ExceptionHandler\n"); // c で次の命令へのアドレスを取得する方法が現在の所は不明。 ExceptionInfo->ContextRecord->Eip += 10; // 例外が発生した次の命令へ飛ばす return(EXCEPTION_CONTINUE_EXECUTION); } int main() { printf("null pointer exception\n"); SetUnhandledExceptionFilt
構造化例外処理では、通常の try-except によるフレームベースの SEH の他、 ベクトル化例外処理 (ベクタ例外処理, Vectored Exception Handling, VEH) もサポートしています。これによって任意の時点での例外ハンドラの登録・解除を可能にします。 ベクトル化例外ハンドラを登録するには、AddVectoredExceptionHandler を使います。 第一引数を非ゼロにすると、例外発生時に最初に呼び出されるハンドラを登録することになります。 第二引数は例外ハンドラ関数のアドレスです。 PVOID WINAPI AddVectoredExceptionHandler( __in ULONG FirstHandler, __in PVECTORED_EXCEPTION_HANDLER VectoredHandler ); 戻り値としては、例外発生時点か
リリース、障害情報などのサービスのお知らせ
最新の人気エントリーの配信
処理を実行中です
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く