12

そのため、私は自分の開発で Qt をよく使用し、気に入っています。Qt オブジェクトの通常の設計パターンは、 を使用してそれらを割り当てることnewです。

std::bad_allocほとんどすべての例 (特に Qt デザイナーによって生成されたコード) は、例外のチェックをまったく行いません。割り当てられるオブジェクト (通常はウィジェットなど) は小さいため、これが問題になることはほとんどありません。結局のところ、20 バイト程度の割り当てに失敗した場合、問題を解決するためにできることはほとんどありません。

現在、「大きな」(サイズが 1 ページまたは 2 ページを超えるもの) 割り当てを try/catch でラップするポリシーを採用しています。それが失敗した場合は、ユーザーにメッセージを表示します。ほとんどの場合、それよりも小さいメッセージを表示します。アプリをクラッシュさせてstd::bad_alloc例外を発生させます。

では、これについてどのような学派が考えているのだろうか?

newすべての操作をチェックするのは良い方針ですか? それとも、失敗する可能性があると私が予想するものだけですか?

また、リソースがはるかに制限される可能性がある組み込み環境を扱う場合は、明らかにまったく別の話です。私はデスクトップ アプリケーションのコンテキストで質問していますが、他のシナリオに関する回答にも興味があります。

4

6 に答える 6

17

問題は「どこでキャッチするか」ではなく、「例外がキャッチされたらどうするか」です。

確認したい場合は、ラップする代わりにtry catch使用した方がよいでしょう

    #include <new>
    x = new (std::nothrow) X();
    if (x == NULL) {
        // allocation failed
    }

私の普段の練習は

  • 非対話型プログラムでは、メイン レベルでキャッチし、そこに適切なエラー メッセージを表示します。

  • ユーザー対話ループを持つプログラムでは、ループ内でもキャッチして、ユーザーがいくつかのものを閉じて続行できるようにします。

例外的に、キャッチが意味を持つ場所は他にもありますが、それはまれです。

于 2009-08-20T18:49:03.320 に答える
11

可能な場合は例外を処理します。割り当てが失敗し、そのビットのメモリがないとアプリケーションを続行できない場合、わざわざエラーをチェックする必要はありません。

意味のある回復方法がある場合は、エラーを処理できる場合にエラーを処理します。エラーについて何もできない場合は、エラーを伝播させてください。

于 2009-08-20T19:03:27.847 に答える
6

私は通常、ユーザーがアクションを開始した時点で例外をキャッチします。コンソール アプリケーションの場合、これはmain.GUI アプリケーションの場合、ボタンのオンクリック ハンドラーなどの場所にハンドラーを配置することを意味します。

アクションの途中で例外をキャッチすることはほとんど意味がないと思います。ユーザーは通常、操作が成功するか完全に失敗することを期待しています。

于 2009-08-20T18:52:33.750 に答える
4

これは比較的古いスレッドですが、2012年にここで新規/削除のオーバーライドを行うときに「std::bad_alloc」の考慮事項を検索していたときに出てきました。

私は、「まあ、とにかく何もできない」という概念を実行可能な選択肢としてとらえません。私は個人的に、上記の「if(alloc()){}else{エラー/処理}」の方法を自分の割り当てで使用しています。このようにして、私は適切に処理し、または、それぞれのケースをそれぞれの意味のあるコンテキストで報告することができます。

現在、他のいくつかの可能な解決策は次のとおりです。1)独自のメモリ不足処理を追加できるアプリケーションの新規/削除をオーバーライドします。

他のポスターのように、特に特定のコンテキストの知識がなくても、主なオプションはおそらくアプリケーションをシャットダウンすることです。この場合、ハンドラーに必要なメモリを事前に割り当てるか、静的メモリを使用して、ハンドラー自体が使い果たされないようにする必要があります。

ここでは、少なくともダイアログがポップアップ表示され、次の行で何かを言うことができます。「アプリケーションのメモリが不足しました。これは致命的なエラーであり、自己終了する必要があります。アプリケーションは最小システムメモリ要件で実行する必要があります。送信デバッグレポートをxxxx"に送信します。ハンドラーは、アプリケーションに合わせて、進行中の作業などを保存することもできます。

いずれにせよ、スペースシャトル、心拍数モニター、腎臓透析装置などの重要なもの(警告、アマチュアのユーモア)にはこれを使用したくないでしょう。もちろん、これらのものには、より堅牢なソリューションが必要です。フェイルセーフ、緊急ガベージコレクション方法、100%テスト/デバッグ/ファジングなど。

2)最初と同様に、グローバルスコープでメモリ不足状態をキャッチするために、独自のハンドラーを使用してグローバル「set_new_handler()」を設定します。少なくとも#1で述べたように物事を処理することができます。

于 2012-01-03T23:35:21.577 に答える
1

本当の問題は、std::bad_alloc 例外をキャッチする必要があるかどうかです。ほとんどの場合、メモリが不足すると、とにかく運命づけられ、プログラムを終了することを検討する可能性があります。

于 2012-08-08T11:09:12.927 に答える
0

main()(または Qt の同等のトップ レベルの例外ハンドラー) で処理します。

その理由は、std::bad_alloc は、メモリ領域を使い果たしたとき (32 ビット システムでは 2 または 3 GB、64 ビット システムでは発生しません)、またはスワップ領域を使い果たしたときに発生するためです。最新のヒープ アロケーターは、スワップ スペースから実行するように調整されていないため、ゆっくりとしたノイズの多い死になります。UI が応答しなくなったため、ユーザーが事前にアプリを強制終了する可能性があります。Linux では、OS のメモリ処理がデフォルトで非常に貧弱であるため、アプリが自動的に強制終了される可能性があります。

そのため、できることはほとんどありません。バグがあることを告白し、ユーザーが行った可能性のある作業を保存できるかどうかを確認します。そうするためには、できるだけ中止するのが最善です。はい、これは実際には最後のユーザー入力の一部を失う可能性があります。しかし、OOM の状況を引き起こした可能性が高いのはまさにそのアクションです。目標は、信頼できるデータを保存することです。

于 2009-08-21T08:05:36.740 に答える