問題タブ [raii]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
perl - Perl で RAII スタイルのリソースを自動的に解放するにはどうすればよいですか?
解放する必要のあるリソース (ファイルハンドルやネットワークソケットなど) があるとします。
それprocess
が死ぬかもしれないとしましょう。その後、コード ブロックは早期に終了し、$fh
閉じられません。
エラーを明示的にチェックできます。
しかし、この種のコードは正しく作成するのが難しいことで有名であり、リソースを追加するとさらに複雑になります。
C++ では、 RAIIを使用して、リソースを所有し、そのデストラクタがそれを解放するオブジェクトを作成します。そうすれば、リソースを解放することを覚えておく必要がなくなり、例外がスローされた場合でも、RAII オブジェクトが範囲外になるとすぐにリソースのクリーンアップが正しく行われます。残念ながら、Perl ではDESTROY
メソッドが呼び出されるタイミングが保証されていないため、メソッドはこの目的には適していません。
例外が存在する場合でも、このようにリソースが自動的に解放されるようにする Perlish の方法はありますか? それとも明示的なエラーチェックが唯一のオプションですか?
.net - ネイティブ (C++) 例外が CLR コンポーネントに伝播するときにデストラクタが呼び出されない
DLL にコンパイルされた大量のネイティブ C++ コードがあります。
次に、C++ インターフェイスをラップする C++/CLI プロキシ コードを含む dll をいくつか用意します。
その上に、C++/CLI ラッパーを呼び出す C# コードがあります。
これまでのところ、標準的なもの。
しかし、ネイティブの C++ 例外が .Net の世界に伝播することが許可されているケースが多くあり、これらを System.Exception オブジェクトとしてラップする .Net の機能に依存しており、ほとんどの場合、これは正常に機能します。
ただし、スローの時点でスコープ内にあるオブジェクトのデストラクタが、例外が伝播したときに呼び出されていないことがわかっています。
いくつかの調査の結果、これはかなりよく知られている問題であることがわかりました。ただし、解決策/回避策は一貫性がないようです。ネイティブ コードを /EHsc ではなく /EHa でコンパイルすると、問題が解消されることがわかりました (少なくとも、テスト ケースでは解消されました)。ただし、SEH 例外を C++ 例外に変換するため、/EHsc を使用することを強くお勧めします。コンパイラに最適化の範囲を広げさせたいと考えています。
(C++/CLI レイヤーに加えて) (ネイティブ) try-catch-throw でネイティブ管理の境界を越えてすべての呼び出しをラップする以外に、この問題に対する他の回避策はありますか?
c++ - 例外が発生したかどうかに応じて、デストラクタにさまざまなアクションを実行させる
次のようなデータベーステーブルを更新するコードがあります
トランザクションロジックをRAIIクラスでラップして、次のように記述できるようにします。
しかし、どのようにデストラクタを作成しますか?
c++ - C++ の RAII チュートリアル
C++ で RAII を使用する方法を学びたいです。それが何であるかはわかっていると思いますが、プログラムに実装する方法がわかりません。簡単な Google 検索では、適切なチュートリアルは表示されませんでした。
RAII を教えてくれる素敵なリンクはありますか?
c++ - RAII テンプレート クラスのオブジェクト ジェネレーターを作成するより良い方法は?
テンプレート化された RAII クラスのオブジェクト ジェネレーターを作成したいと思います。基本的には、パラメーターの型推定を使用してオブジェクトを構築するための関数テンプレートであるため、型を明示的に指定する必要はありません。
私が予見する問題は、型推論を処理するヘルパー関数がオブジェクトを値で返すことであり、(**) コピーが作成されたときに RAII デストラクタへの早すぎる呼び出しが発生します。おそらく C++0x の移動セマンティクスが役立つかもしれませんが、それは私にとっては選択肢ではありません。
以前にこの問題を見て、良い解決策を持っている人はいますか?
これは私が持っているものです:
要点はOtherThing
、ひどいインターフェースを持ち、FooAdder
使いやすくすることになっています。使用目的はおおよそ次のようになります。
コンストラクターは、FooAdder
いくつかの内部データ構造を初期化します。foo
およびメソッドは、bar
これらのデータ構造にデータを取り込みます。~FooAdder
dtor は物事をまとめて on のメソッドを呼び出し、すべての煩わしさを処理thing_
します。
FooAdder
テンプレじゃなくても大丈夫です。しかし、そうなので、次のように型を入れる必要があります。
に基づいて型を推測できるため、面倒ですmyThing
。したがってstd::make_pair
、型推論を行う のような、テンプレート化されたオブジェクト ジェネレーターを作成することをお勧めします。このようなもの:
これには問題があるようです: 値によって返されるため、スタック一時オブジェクトが (**) 破棄され、RAII dtor が途中で実行されます。
** - RVO が実装されていない場合。ほとんどのコンパイラはこれを行いますが、必須ではなく、gcc で を使用してオフにすることができます-fno-elide-constructors
。
c++ - スマートポインタに含まれているリソースの解放の失敗を処理するにはどうすればよいですか?
リソースを表すオブジェクトが共有ポインターに含まれている場合、リソースの割り当て解除中のエラーはどのように処理する必要がありますか?
編集1:
この質問をより具体的に言うと、多くのCスタイルのインターフェースには、リソースを割り当てる機能と、リソースを解放する機能があります。例としては、POSIXシステムのファイル記述子の場合はopen(2)とclose(2)、Xサーバーへの接続の場合はXOpenDisplayとXCloseDisplay、SQLiteデータベースへの接続の場合はsqlite3_openとsqlite3_closeがあります。
このようなインターフェイスをC++クラスにカプセル化し、Pimplイディオムを使用して実装の詳細を非表示にし、共有ポインターを返すファクトリメソッドを提供して、リソースへの参照が残っていないときにリソースの割り当てが解除されるようにします。
ただし、上記のすべての例および他の多くの例では、リソースの解放に使用された関数がエラーを報告する場合があります。この関数がデストラクタによって呼び出された場合、通常、デストラクタはスローしてはならないため、例外をスローすることはできません。
一方、リソースを解放するためのパブリックメソッドを提供する場合、2つの可能な状態を持つクラスがあります。1つはリソースが有効であり、もう1つはリソースがすでに解放されています。これはクラスの実装を複雑にするだけでなく、誤った使用法の可能性も開きます。インターフェイスは使用エラーを不可能にすることを目的としているため、これは悪いことです。
この問題について助けていただければ幸いです。
質問の元のステートメント、および可能な解決策についての考えは以下のとおりです。
編集2:
現在、この質問には報奨金があります。ソリューションは次の要件を満たす必要があります。
- リソースへの参照が残っていない場合にのみ、リソースが解放されます。
- リソースへの参照は明示的に破棄される可能性があります。リソースの解放中にエラーが発生した場合、例外がスローされます。
- すでにリリースされているリソースを使用することはできません。
- リソースの参照カウントと解放はスレッドセーフです。
ソリューションは次の要件を満たす必要があります。
- これは、 boost、C ++テクニカルレポート1(TR1)、および今後のC++標準であるC++0xによって提供される共有ポインターを使用します。
- それは一般的です。リソースクラスは、リソースの解放方法を実装するだけで済みます。
お手数をおかけしますが、よろしくお願いいたします。
編集3:
私の質問に答えてくれたみんなに感謝します。
アルスクの答えは、賞金で要求されたすべてを満たし、受け入れられました。マルチスレッドコードでは、このソリューションには個別のクリーンアップスレッドが必要になります。
別のクリーンアップスレッドを必要とせずに、クリーンアップ中の例外が実際にリソースを使用したスレッドによってスローされるという別の回答を追加しました。あなたがまだこの問題に興味を持っているなら(それは私をとても悩ませました)、コメントしてください。
スマートポインタは、リソースを安全に管理するための便利なツールです。このようなリソースの例としては、メモリ、ディスクファイル、データベース接続、またはネットワーク接続があります。
典型的なシナリオでは、リソースをカプセル化するクラスはコピー不可能でポリモーフィックである必要があります。これをサポートする良い方法は、共有ポインターを返すファクトリメソッドを提供し、すべてのコンストラクターを非公開として宣言することです。これで、共有ポインタを自由にコピーして割り当てることができます。オブジェクトへの参照がなくなると、オブジェクトは自動的に破棄され、デストラクタはリソースを解放します。
しかし、このアプローチには問題があります。デストラクタはスローしてはならないため、リソースの解放の失敗は検出されないままになります。
この問題を解決する一般的な方法は、リソースを解放するためのパブリックメソッドを追加することです。
残念ながら、このアプローチでは別の問題が発生します。オブジェクトには、すでにリリースされているリソースが含まれている可能性があります。これにより、リソースクラスの実装が複雑になります。さらに悪いことに、クラスのクライアントがそれを誤って使用する可能性があります。次の例はとてつもないように見えるかもしれませんが、マルチスレッドコードの一般的な落とし穴です。
オブジェクトが破棄される前にリソースが解放されないようにすることで、失敗したリソースの割り当て解除に対処する方法が失われます。または、オブジェクトの存続期間中にリソースを明示的に解放する方法を提供します。これにより、リソースクラスを誤って使用できるようになります。
このジレンマから抜け出す方法があります。ただし、解決策には、変更された共有ポインタークラスを使用することが含まれます。これらの変更は物議を醸す可能性があります。
boost :: shared_ptrなどの一般的な共有ポインタの実装では、オブジェクトのデストラクタが呼び出されたときに例外がスローされないようにする必要があります。一般に、デストラクタはスローしてはならないため、これは妥当な要件です。これらの実装では、オブジェクトへの参照が残っていない場合にデストラクタの代わりに呼び出されるカスタム削除関数を指定することもできます。スローなしの要件は、このカスタム削除機能に拡張されています。
この要件の論理的根拠は明らかです。共有ポインタのデストラクタはスローしてはなりません。削除関数がスローしない場合、または共有ポインターのデストラクタもスローしません。ただし、同じことが、リソースの割り当て解除につながる共有ポインターの他のメンバー関数にも当てはまります。たとえば、reset():リソースの割り当て解除が失敗した場合、例外をスローすることはできません。
ここで提案する解決策は、カスタム削除関数をスローできるようにすることです。これは、変更された共有ポインタのデストラクタが、deleter関数によってスローされた例外をキャッチする必要があることを意味します。一方、デストラクタ以外のメンバー関数(reset()など)は、デリータ関数の例外をキャッチしてはなりません(その実装はやや複雑になります)。
スロー削除関数を使用した元の例を次に示します。
これで、reset()を使用してリソースを明示的に解放できます。別のスレッドまたはプログラムの別の部分にリソースへの参照がまだある場合、reset()を呼び出すと、参照カウントがデクリメントされるだけです。これがリソースへの最後の参照である場合、リソースは解放されます。リソースの割り当て解除が失敗すると、例外がスローされます。
編集:
削除機能の完全な(ただしプラットフォームに依存する)実装は次のとおりです。
java - 〜1sレイテンシー制御アプリ:これはJavaに適していますか?
私の仕事では、最近、最大遅延が約1〜2秒の制御アプリケーションのシステムアーキテクチャを完成させました。これは、IPLANを介して通信する小さなARMオンチップボックスに配布されます。
CまたはC++は古典的な制御システム言語であるため、最初はCまたはC++を使用することを想定しています。アプリケーションの実装方法について話し合った後、C ++にはライブラリの数が非常に限られており、内省がなく、開発を遅らせる可能性のある他のいくつかのプロパティがあることがわかりました。それから私の同僚は、Javaがその仕事に向いているかもしれないと提案しました。
コントロールアプリでGCを実行するまでの待ち時間が本当に怖いです。また、アプリが多くの外部リソース(ソケット、ファイルハンドル、外部ライブラリからのハンドルなど)を使用するため、RAIIを削除することにも消極的です。
賛否両論のリストは現在次のとおりです。
パラレルGCによるメモリの断片化は、このAMDの記事で言及されています
GCのレイテンシーが問題でなく、RAIIを取得できれば、Javaを使用したいと思います。したがって、RAIIがあり、優れた代替手段として役立つ可能性のある他の言語も調べました。これまでのところ、D、Ada、VB、Perl、Python(C)、PHP、tcl、およびLuaには何らかの種類があるようです。範囲外のコールバックの。おそらくD、Python、ADAがコントロールアプリに適している可能性があるという私の自発的な反応。DとADAが私のお気に入りです。
だから、私の質問は:これについて何かアドバイスはありますか?Javaは実行可能なオプションであり、任意の言語を選択できるとしたら、それは何でしょうか。
c++ - CTOR およびスマート ポインターでの例外のスロー
コンストラクターに次のコードを入れて、XML ドキュメントをメンバー変数にロードしても問題ありませんか? 問題がある場合は、呼び出し元にスローします。
より効果的な C++ での Scott Myers RAII 実装に基づいて、リソース、つまりポインターを割り当てる場合、彼はクリーンアップします。
スマート ポインター (IXMLDOMDocumentPtr) を使用しているため、CTOR から例外をスローできるようにするだけで問題ないと思います。
どう考えているか教えてください....
c++ - TDDとRAIIの混合方法
新しいプロジェクトの広範なテストを行おうとしていますが、問題があります。
基本的にはMyClassをテストしたいと思います。MyClassは、テストの目的で、私がその仕事をする必要がない/したくない他のいくつかのクラスを利用します。そこで、モックを作成しました(テストにはgtestとgmockを使用します)
ただし、MyClassは、コンストラクタで必要なものをすべてインスタンス化し、デストラクタで解放します。それがRAIIだと思います。
そこで、すべてを作成してMyClassのコンストラクターに渡す、ある種のファクトリを作成する必要があると思いました。その工場は、テスト目的で偽物である可能性があります。しかし、それはもはやRAIIではありませんか?
では、ここでの良い解決策は何ですか?
c++ - 参照カウントが0に達したら、shared_ptrがメンバー関数を呼び出すようにする
DuplicateHandleで動作しないHANDLEのラッパーを作成しているので、代わりに、shared_ptrでハンドルをラップしようとしています。
次のコードを想像してみてください。
また、HANDLEパラメーターを使用してcloseを作成してみました(理想的ではありません)。いずれにせよ、「Termは0個の引数を取る関数に評価されません」というコンパイラエラーが発生します。これは暗黙のthisポインタによるものですか?これを修正するにはどうすればよいですか?共有ポインタからメンバー関数を呼び出すにはどうすればよいですか?