cコールバック - 悪い考えで{} catch(...){}を試してみてください。 -- c++ フィールド と exception-handling フィールド と callback フィールド 関連 問題

try{ } catch(…) { } in C callback - bad idea?












12
vote

問題

日本語

通常のCコードから呼び出されるC ++でコールバックを実装しています。 My Main()関数はすでにC ++ですが、Cコードは最終的にコールバックを呼び出すスレッドを作成する責任があります。

今私のコールバックは

のように見えます <事前> <コード> int handle_foo(void *userdata) { try { MyCPPClass *obj = static_cast<MyCPPClass *>(userdata); obj->doStuff(); return 0; // no error } catch(...) { LogError("doStuff failed"); return -1; // error } }

これは大丈夫ですが、それは私に変わっているようです。さらに、を見つけた能力などの便利な機能を失います。が投げられたが投げられたもの(巨大な量の<コード> 99887661 ステートメントをそれぞれおよびすべてのコールバックに追加することなく)。

はここで妥当なものである、または私のCコールバックを書くより良い方法はありますか?

英語

I'm implementing callbacks in C++ which will be called from ordinary C code. My main() function is C++ already, but C code will be responsible for creating threads that will eventually call my callbacks.

Right now my callbacks look like

int handle_foo(void *userdata) {     try {         MyCPPClass *obj = static_cast<MyCPPClass *>(userdata);         obj->doStuff();         return 0; // no error     } catch(...) {         LogError("doStuff failed");          return -1; // error     } } 

This works OK, but it seems weird to me. Furthermore, I lose some useful features such as the ability to find out what was thrown (without adding huge amounts of extra catch statements to each and every one of my callbacks).

Is try {} catch(...) {} here reasonable, or is there a better way to write my C callbacks?

</div
        
   
   

回答リスト

7
 
vote
vote
ベストアンサー
 

はい、あなたは例外を捕まえて、それらを何か便利なものに翻訳する必要があります。例外がCコードを伝播させることは未定義の行動につながります。最善では、Cコードが一貫したプログラム状態を維持することを期待することはできません。

簡単な例では、この回答を参照してください。より困難な例は、SQLite-Cコードのようないくつかの複雑なソフトウェアがいくつかのソフトウェアであり、単に「飛行する」とあなたのプログラムが今すぐトーストになっているためにそれを解放することはありません。

また、すべてのコードが同じC ++ランタイムに対して構築されている場合は、「作業」の可能性があります。 Visual C ++ 9との残りのコードが静的ランタイムライブラリに対してコンパイルされていると、Visual C ++ 9との残りのコードが実装されている場合は、次に2つの異なるランタイムと、コールバックの未処理の例外が2つあります。 recordsTotal3 が呼び出されています。

 

Yes, you have to catch the exceptions and hopefully translate them into something useful. Letting exceptions propagate through C code leads to undefined behavior. At best you cannot expect the C code to maintain consistent program state.

See this answer for an easy example. A harder example is with some complex piece of software such as SQLite - C code will grab some mutex and will not release it because the exception simply "flies through" and your program is now toast.

Also this has any chance of "working" if all the code is built against the same C++ runtime. If you happen to have callback implemented in say Visual C++ 9 and the rest of the code in say Visual C++ 10 or those parts are compiled against static runtime libraries - you now have two distinct runtimes and the unhandled exception in the callback causes terminate() being called.

</div
 
 
       
       
3
 
vote

Sharptoothはあなたの質問のほとんどに答え、James McNellisは素晴らしい Blog Post 現代のC ++を使ってボイラープレートを取り除く方法について

その要旨は、このように使用されているTranslate_Exceptions関数を持つことです:

<事前> <コード> int callback(...) { return translate_exceptions([&]{ // ... your code here }); }

translate_exceptionは、呼び出し可能なものを取っている単純な関数テンプレート(関数レベル試行ブロックを使用します)です。

<事前> <コード> template<typename Fn> int translate_exception(Fn fn) try { fn(); return 0; } catch(std::exception const& e) { LOG("[EE] exception ", e.what()); return -2; } catch( ... ) { LOG("[EE] unknown exception"); return -1; }
 

sharptooth answered most of your question, and James McNellis has written a nice blog post about how to elegantly get rid of the boilerplate using modern C++.

The gist of it is having a translate_exceptions function used like this:

int callback(...) {    return translate_exceptions([&]{       // ... your code here    }); } 

The translate_exception is a simple function template (which uses a function level try block) taking an invokable:

template<typename Fn> int translate_exception(Fn fn) try {   fn();   return 0; } catch(std::exception const& e) {   LOG("[EE] exception ", e.what());   return -2; } catch( ... ) {   LOG("[EE] unknown exception");   return -1; } 
</div
 
 

関連する質問

4  submit()関数にコールバックがありますか?  ( Does submit function has a callback ) 
私はこのコードを持っています、そしてフレームに提出されたファイルのアップロードフォーム: <事前> <コード> setMyCookie('name','value_1'); $('.myform').submit(); setMyCookie('name','...

0  iOS - CFSocketはコールバックを取得しません  ( Ios cfsocket not getting callback ) 
類似の質問が求められましたが、問題は非常にコード固有のようです、とてもうまくいけばこれは大丈夫です。 UDPブロードキャストを聴取し、データに行動するiOSアプリケーションを作成しようとしています。この種の機能を実装するためにバックグラウンドスレッドと生の...

0  私のアプリでさえも私のオブジェクトを生きる方法  ( How to make my object live even my app closed ) 
シンプルさのための2つのアプリがある状況を得ました APP1 APP2 として、オブジェクト<コード> remoteCallback をとして渡しています。将来の使用のためのApp1からApp2へのコード> CALLBACK 。 結果App2に基づく upd...

0  サーバーサイドコールバック機能AJAX WebサービスASP.NET  ( Server side callback function ajax web service asp net ) 
私のプロジェクトでAjax要求を処理するためにWebサービスを使用しています。新しい要求が続行されたときにオンラインでユーザーをカウントするためにサーバー側関数を呼び出す必要があります。 ...

326  JavaScriptでカスタムコールバックを作成します  ( Create a custom callback in javascript ) 
現在の関数の実行が終了したときにコールバック関数を実行することはすべて実行することです。 <事前> <コード> function LoadData() { alert('The data has been loaded'); //Call m...

2  GetCallBackeVentReferenceは同期的には機能しません  ( Getcallbackeventreference doesnt work synchronously ) 
私はフレームワークのページを活用するASP.NET 3.5 Webformを持っています.ClientScript.getCallBackeVentReference()メソッドは、どちらの呼び出しを同期させる必要があります。 今、文書は5番目のパラメータ(...

4  長いタスク中にアプリを応答して保持します  ( Keep app responsive during long task ) 
私たちのアプリケーションの特定の形式でモデルのグラフィカルなビューが表示されます。ユーザは、他のものの負荷の中でも、かなり時間がかかることがあるモデルの変換を開始することができる。この変換は、他の時には頻繁なユーザー入力が必要であるため、ユーザーの相互作用なし...

0  Geo.GetLocations(Googleマップ)で非同期通話のALLE結果を収集できません。  ( Cannot collect alle results of asynchronous call with geo getlocations google m ) 
下のは私のコードです。問題は、RecordsOut [0]が常に未定義であることです。 私はそれがコールバック結果と関係があることを知っています。結果を返すのにもっと時間を与えるためにいくつかの遅延を追加しようとしましたが、それは役に立ちませんでした。 任意の...

159  Cでは「コールバック」とは何ですか?それらはどのように実装されていますか?  ( What is a callback in c and how are they implemented ) 
私が完了した読みから、コアオーディオはコールバック(そしてC ++ですが、それが別のストーリーです)に大きく依存しています。 タスクを達成するために他の関数によって呼び出される関数を繰り返し設定するという概念(並み)を理解しています。私は彼らがどのように設定...

2  私はJSONの反応を持っていますが、それを解析することはできません。手助けが必要です。 jQueryなしプロトタイプはありません。 JavaScriptだけ  ( I have a json response but cant parse it help required no jquery no prototype ) 
だから私はJSONを使っていくつかのISSUSを持っています。 <事前> <コード> setupdata({"NON-RELIGOUS ORGANIZATIONS":{"23":["NON-RELIGOUS ORGANIZATIONS","Does this...




© 2022 cndgn.com All Rights Reserved. Q&Aハウス 全著作権所有