問題タブ [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.
c++ - ScopeGuard の使用は本当にコードの改善につながるのでしょうか?
Andrei Alexandrescu と Petru Marginean によって何年も前に書かれたこの記事に出くわしました。この記事では、例外セーフ コードを作成するための ScopeGuard と呼ばれるユーティリティ クラスを紹介し、説明しています。これらのオブジェクトを使用したコーディングが本当により良いコードにつながるのか、それともエラー処理を難読化するのかを知りたいのですが、おそらくガードのコールバックは catch ブロックでより適切に提示されるでしょうか? 実際の製品コードでこれらを使用した経験がある人はいますか?
c# - ネストされた「使用」よりも優れた決定論的廃棄パターンはありますか?
C#では、管理されていないリソースを決定論的にクリーンアップする場合は、「using」キーワードを使用できます。しかし、複数の依存オブジェクトの場合、これはさらにネストすることになります。
C ++では、デストラクタを使用して次のように実行できることに慣れています。
これを行うためのC#のより良い方法はありますか?それとも、複数のレベルのネストに固執していますか?
c++ - C++ でメモリ リークを回避するための一般的なガイドライン
C++ プログラムでメモリ リークを起こさないようにするための一般的なヒントは何ですか? 動的に割り当てられたメモリを誰が解放する必要があるかを知るにはどうすればよいですか?
c++ - 標準コンテナで std::auto_ptr<> を使用するのが間違っているのはなぜですか?
std::auto_ptr<>
標準コンテナでの使用が間違っているのはなぜですか?
c++ - デストラクタで例外をスローしてはならない場合、デストラクタでエラーをどのように処理しますか?
ほとんどの人は、デストラクタから例外をスローしないと言っています。そうすると、未定義の動作が発生します。Stroustrup は、「ベクトル デストラクタはすべての要素に対して明示的にデストラクタを呼び出すことを強調しています。これは、要素デストラクタがスローした場合、ベクトルの破壊が失敗することを意味します...デストラクタからスローされた例外から保護する良い方法は実際にはありません。そのため、ライブラリは要素デストラクタがスローするかどうかは保証しません」(付録 E3.2 より)。
この記事では、デストラクタのスローは多かれ少なかれ問題ないと言っているようです。
だから私の質問はこれです - デストラクタからスローすると未定義の動作になる場合、デストラクタ中に発生したエラーをどのように処理しますか?
クリーンアップ操作中にエラーが発生した場合、それを無視しますか? スタックで処理できる可能性があるが、デストラクタで正しく処理できないエラーである場合、デストラクタから例外をスローするのは理にかなっていませんか?
明らかに、この種のエラーはまれですが、発生する可能性があります。
c++ - RAIIと例外
C ++でRAIIを使用すればするほど、重要な割り当て解除を行うデストラクタを使用するようになります。現在、割り当て解除(ファイナライズ、ただし、それを呼び出したい場合)は失敗する可能性があります。その場合、例外は、実際には、2階の誰かに割り当て解除の問題を知らせる唯一の方法です。ただし、スタックの巻き戻し中に例外がスローされる可能性があるため、スローデストラクタはお勧めできません。std::uncaught_exception()
それがいつ発生するかを知らせますが、それ以上ではありません。したがって、終了前にメッセージをログに記録できるようにする以外に、プログラムを未定義の状態のままにしておく場合を除いて、できることはほとんどありません。とそうでないものもあります。
1つのアプローチは、スローしないデストラクタを使用することです。しかし、多くの場合、それは実際のエラーを隠すだけです。たとえば、デストラクタは、いくつかの例外がスローされた結果として、一部のRAII管理のDB接続を閉じている可能性があり、それらのDB接続は閉じられない可能性があります。これは、プログラムがこの時点で終了しても問題がないことを必ずしも意味するものではありません。一方、これらのエラーをログに記録して追跡することは、実際にはすべての場合の解決策ではありません。そうでなければ、そもそも例外は必要ありませんでした。スローしないデストラクタを使用すると、破棄前に呼び出されるはずの「reset()」関数を作成する必要がありますが、これはRAIIの目的全体を損なうだけです。
もう1つのアプローチは、プログラムを終了させることです。これは、実行できる最も予測可能なことです。
一度に複数のエラーを処理できるように、例外を連鎖させることを提案する人もいます。しかし、正直なところ、C ++で行われることを実際に見たことがなく、そのようなことを実装する方法がわかりません。
つまり、RAIIまたは例外のいずれかです。ではない?私はスローしないデストラクタに傾いています。主にそれが物事を単純に保つからです(r)。しかし、私が言ったように、RAIIを使用すればするほど、重要なことを行うdtorを使用するようになるので、より良い解決策があることを本当に望んでいます。
付録
私が見つけた興味深い話題の記事やディスカッションへのリンクを追加しています:
- デストラクタを投げる
- SEHの問題に関するStackOverflowの議論
- スローイングデストラクタに関するStackOverflowディスカッション(ありがとう、Martin York)
- Joel on Exceptions
- SEHは有害だと考えられています
- 例外チェーンにも触れるCLR例外処理
- std::uncaught_exceptionのハーブサッターとそれが思ったほど役に立たない理由
- 興味深い参加者との問題に関する歴史的な議論(長い!)
- RAIIを説明するStroustrup
- アンドレイ・アレキサンドレスのスコープガード
c++ - C++ 以外の他の言語のプログラマーは、RAII を使用、認識、または理解していますか?
RAII が Stackoverflow で多くの注目を集めていることに気付きましたが、私のサークル (ほとんどが C++) では、RAII は非常に明白で、何がクラスかデストラクタかを尋ねるようなものです。
だから、私が毎日ハードコアな C++ プログラマーに囲まれていて、RAII が一般的に (C++ を含めて) あまり知られていないからなのか、それとも Stackoverflow に関するこのすべての質問が事実によるものなのか、非常に興味があります。私は今、C++ で育ったのではなく、他の言語では RAII を使用していない/知らないプログラマーと連絡を取り合っているということですか?
.net - .NET に RAII がないのはなぜですか?
主に C++ の開発者である私は、Java と .NET にRAII (Resource Acquisition Is Initialization)がないことにいつも悩まされてきました。クリーンアップの責任がクラスの作成者から消費者に移されたという事実 (try finally
または .NET のusing
コンストラクトによって) は、著しく劣っているように思われます。
すべてのオブジェクトがヒープ上にあり、ガベージ コレクターが本質的に決定論的破壊をサポートしていないため、Java で RAII がサポートされていない理由がわかりましたが、値型 ( struct
) の導入により .NET では (一見) RAIIの完璧な候補。スタック上に作成された値型には明確に定義されたスコープがあり、C++ デストラクター セマンティクスを使用できます。ただし、CLR では、値型がデストラクタを持つことは許可されていません。
私のランダムな検索では、値の型がボックス化されている場合、ガベージ コレクターの管轄下にあるため、その破棄が非決定的になるという 1 つの引数が見つかりました。この議論は十分に強力ではないと感じています。RAII の利点は、デストラクタを持つ値型をボックス化 (またはクラス メンバーとして使用) できないと言うのに十分大きいです。
簡単に言うと、私の質問は次のとおりです。RAII を .NET に導入するために値型を使用できない理由は他にありますか? (または、RAII の明らかな利点についての私の議論には誤りがあると思いますか?)
編集:最初の4つの回答が要点を逃したため、質問を明確に表現していなかったに違いありません。私はその非決定論的特性について知っており、構造について知っており、これら2つのオプションは RAII よりも劣っていると感じています。は、クラスの消費者が覚えておかなければならないもう 1 つのことです (ブロックに aを入れるのを忘れた人は何人いますか?)。私の質問は、言語設計に関する哲学的なものです。なぜそうなのか、改善できるのでしょうか?Finalize
using
using
StreamReader
using
たとえば、一般的な決定論的に破壊可能な値型を使用すると、using
andlock
キーワードを冗長にすることができます (ライブラリ クラスによって達成可能)。
私は、かつて見たが、現在その出所を見つけることができない適切な引用で終わらせざるを得ません。
私の冷たい死んだ手が範囲外になると、私の決定論的破壊を受け取ることができます. --アノン
java - Java の RAII... リソースの処分はいつもとても醜いですか?
Java ファイル システム API をいじってみたところ、バイナリ ファイルのコピーに使用される次の関数が思い浮かびました。元のソースは Web から取得しましたが、try/catch/finally 句を追加して、何か問題が発生した場合に、関数を終了する前にバッファー ストリームが閉じられる (したがって、OS リソースが解放される) ようにしました。
パターンを表示するために関数を縮小しました。
私が理解している限りでは、2 つclose()
を finally 句に入れることはできません。1 つ目は問題close()
なくスローでき、2 つ目は実行されないからです。
C# には、キーワードでこれを処理するDisposeパターンがあることを知っています。using
私は、C++ コードが (Java のような API を使用して) 次のようになることをよく知っています。
何か不足していますか、それともclose()
Buffered Stream のメソッドで例外を処理するためだけに、Java で見苦しく肥大化したコードを作成する必要があるのでしょうか?
(どこか間違っているので教えてください...)
編集:それは私ですか、それともこのページを更新したときに、質問とすべての回答の両方が数分で1ポイント減少したのを見ましたか? 誰かが匿名のままで楽しみすぎていませんか?
編集 2: McDowellは、私がここで言及しなければならないと感じた非常に興味深いリンクを提供しました: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html
編集 3: McDowell のリンクに続いて、パターンを使用する C# に似たパターンの Java 7 の提案を見つけました: http://tech.puredanger.com/java7/#resourceblock。私の問題は明示的に説明されています。どうやら、Java 7 でもdo
、問題は残っています。