20

私は 1 つのプロジェクトで C を使用する必要がありlongjmp/setjmp、エラー処理に使用することを考えています。リターン コードよりも中央の 1 か所でエラーを処理する方がはるかに簡単だと思うからです。これを行う方法についていくつかの手がかりがあれば幸いです。

そのようなエラーが発生した場合に、リソースのクリーンアップが正しく行われることに特に関心があります。

また、それらを使用するマルチスレッド プログラムで発生するエラーをどのように処理すればよいですか?

さらに良いことに、エラー/例外処理用に既に存在する C ライブラリはありますか?

4

6 に答える 6

14

リソースのクリーンアップについて心配している場合は、longjmp() と setjmp() が良いアイデアかどうかを真剣に考える必要があります。

実際に正確にクリーンアップできるようにリソース割り当てシステムを設計する場合は問題ありませんが、コードが使用する標準ライブラリ自体がリソースを割り当てなければならない場合、その設計は扱いにくく、通常は不完全になる傾向があります。解放されます。これには細心の注意が必要であり、完全に信頼できるわけではないため、setjmp()/longjmp() 呼び出しの複数回の使用に耐えなければならない可能性のある長期実行システムには適していません (リーク、拡張、最終的には問題)。

于 2009-05-04T17:44:23.820 に答える
13

この例/チュートリアルを見てください:
http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html

于 2009-05-04T15:12:11.377 に答える
5

私はこれまでに1つの用途しか見つけsetjmp()/longjmp()ていませんが、それはエラー処理とは関係ありませんでした。

常にフォローしやすいものにリファクタリングできるため、実際にそのために使用する必要はありません。の使用法は、簡単に悪用される可能性があるという点でsetjmp()/longjmp()非常に似ています。gotoコードを読みにくくするものは、一般的に悪い考えです。それらが本質的に悪いと言っているのではなく、他の方法よりも簡単に悪いコードにつながる可能性があることに注意してください。

FWIW、彼らがかけがえのない場所の1つは、私が業界の初期に行ったプロジェクト(MS-DOS 6の時間枠)でした。yield()私は、タスクを切り替える関数でこれらの関数を使用するTurbo Cを使用して、協調的なマルチスレッドライブラリをまとめることができました。

当時から彼らに触れていない(または触れる必要があった)と確信しています。

于 2009-05-04T12:32:58.780 に答える
5

Symbianは、そのLeaveメカニズムを次の点で実装しlongjmp()ました。これは、実行する必要のあるすべてのことを順を追って説明するのに役立ちます。

Symbianにはグローバルな「クリーンアップスタック」があり、ジャンプが発生した場合にクリーンアップしたいものをプッシュしてポップします。これは、C++例外がスローされたときにC++コンパイラが実行する自動スタックアンワインドの手動による代替手段です。

Symbianには、ジャンプする「トラップハーネス」がありました。これらはネストできます。

(Symbianは最近、C ++例外に関して再実装しましたが、インターフェイスは変更されていません)。

全体として、適切なC ++例外は、コーディングエラーが発生しにくく、独自のC同等の例外をロールするよりもはるかに高速であると思います。

(最新のC ++コンパイラは、たとえば、スローされない場合の「オーバーヘッドゼロ」例外に非常に優れています。longjmp()ジャンプが後で行われない場合でも、すべてのレジスタの状態などを格納する必要があるため、基本的に、これほど高速になることはありません。例外。)

例外とRAIIのみを採用するより良いCとしてC++を使用することはlongjmp()、例外エミュレーションに使用するのに適したルートです。

于 2009-05-04T12:35:42.970 に答える
0

例外ははるかに優れた一般的なメカニズムですが、C の過去の暗黒時代に、コマンド シェルを含むプロセッサ エミュレーターを作成しました。シェルは、割り込み処理のために jmp/longjmp を設定していました (つまり、プロセッサが実行中で、ユーザーが break/ctrl-c を押すと、コードは SIGINT をトラップし、longjmp をシェルに戻します)。

于 2009-05-04T12:54:06.403 に答える
0

setjmp/を使用longjmpして、コールバック内から抜け出すために、他のさまざまなライブラリ レベルを介して交渉する必要はありませんでした。

そのケース (私の記憶が正しければ) は、yacc によって生成されたパーサー内のコードが (非構文上の) 問題を検出でき、解析を放棄したいが、妥当なエラー レポートを呼び出し元に返したい場合でした。 yacc によって生成されたすべてのコード。別の例は、Expat パーサーから呼び出されたコールバック内にありました。いずれの場合も、これを行う他の方法がありましたが、この方法で単に救済するよりも面倒でわかりにくいように思えました。

ただし、他の回答が指摘しているように、クリーンアップに注意する必要がありlongjmpsetjmp.

マルチスレッドプログラミングのコンテキストでそれを行うのですか? それは不可能ではないと確信していますが、ああ、アスピリンのファミリーパックを今すぐ取り出してください. setjmp/のlongjmpペアをできるだけ近くに保つのがおそらく賢明です。一致するsetjmp/longjmpペアが同じスレッド内にある限り、問題ないと思いますが、注意してください。

于 2014-08-12T15:37:23.480 に答える