1

次のメソッド (Visual Studio 2008 ref クラス内) には、キャッチされると思われる単純なエラーが含まれていますが、代わりに、「Debug Assertion Failed!」でプロセスが中止されます。メッセージ ボックス (msg には、問題のある STL ベクトル src line# が含まれています)。これは、デバッグ モードまたはリリース モードでコンパイルされた場合に発生します。この場合のプロセスは Excel.exe であり、メソッドは COM 相互運用機能を介してアクセスされます。

このエラーがトラップされない理由を教えてもらえますか?

    String^ FOO()
    {
        try {
            std::vector<int> vfoo;
            vfoo.push_back(999);
            return vfoo[1].ToString();  //!!!! error: index 1 not valid
        }
        catch(std::exception& stdE) { // not catching
            return "Unhandled STL exception";
        }
        catch(System::Exception^ E) { // not catching
            return "Unhandled .NET exception: " + E->Message;
        }
        catch(...) { // not even this is catching
            return "Unhandled exception";
        }
    }
4

2 に答える 2

4

デバッグ構成では、反復子デバッグ機能によって有効になっているアサートを取得します。標準 C++ ライブラリの使用における間違いを見つけるのに役立つように設計されています。[コール スタック] ウィンドウを使用して、アサートをトリガーしたコード内のステートメントまでさかのぼることができます。この機能は _HAS_ITERATOR_DEBUGGING マクロによって制御されます。Debug ビルドでこれをオフにする理由はほとんどありません。まあ、どれも。

リリース構成では、VS2005 で導入され、_SECURE_SCL マクロによって制御される Secure CRT Library イニシアチブの一部である Checked Iterators 機能に遭遇します。上記と同じように、デバッガーを停止させるためのフックが組み込まれており、爆撃した理由を示します。ただし、デバッガーがないわけではありません。デバッガーが接続されていない場合、SEH 例外コード 0xc0000417 でプログラムがすぐに終了します。CRT の DLL バージョンは _SECURE_SCL を有効にしてビルドされており、マネージ コードを記述するときにその DLL を使用しないという選択肢はありません。完全にオフにするには /MT を使用してビルドする必要がありますが、C++/CLI ではそれができません。

これは、C++ プログラマーをかなり馬鹿にする傾向があります。catch (...) {} は、プログラムの状態を復元する可能性がゼロに非常に近いにもかかわらず、恵まれた言語機能です。ただし、バックドアがあります (常にバックドアがあります)。引数検証コードは、関数ポインターを介してエラー状態を発行します。デフォルトのハンドラーは、SetUnhandledExceptionFilter() を使用しても、プログラムをキャッチする方法がなく、すぐにプログラムを中止します。ハンドラーを _set_invalid_parameter_handler() 関数に置き換えることができます。これは、次のような Main() メソッドで行う必要があります。

#include "stdafx.h"
#include <stdlib.h>

using namespace System;

#pragma managed(push, off)
void no_invalid_parameter_exit(const wchar_t * expression, const wchar_t * function, 
                               const wchar_t * file, unsigned int line, uintptr_t pReserved) {
    throw new std::invalid_argument("invalid argument");
}
#pragma managed(pop)

int main(array<System::String ^> ^args)
{
    _set_invalid_parameter_handler(no_invalid_parameter_exit);
    // etc...
}

あなたのキャッチハンドラーの1つを実行します。管理されたもので、何が起こったのかを示すまともなパンくずリストはありませんが、ネイティブ C++ の例外では正常です。

于 2012-09-01T21:53:38.857 に答える
0

「デバッグ アサーションに失敗しました!」assert() のようなチェックのように聞こえます。これらは例外ではありません。

実際には、プログラミング エラーを構成するすべてのものに対して assert() スタイルのチェックを使用し、実行時エラーには例外を使用します。おそらく、Microsoft も同様のポリシーに従っています。「範囲外のインデックス」は明らかにプログラミングエラーであり、ディスクがいっぱいになったなどによって引き起こされるものではありません。

于 2012-09-01T21:04:14.623 に答える