19

たとえば、次のコードで、 または のいずれFoo()Bar()が実行されると確信できるかどうかに興味があります。

try {
    ... // Assume there is no return statement here
    Foo();
} catch (Exception e) {
    Bar();
}

私はfinallyブロックについてよく知っているので、その機能についての説明は必要ありません。

難しい方法で発見した の存在により、上記のコードが Java では機能しないため、質問します。Throwable

4

4 に答える 4

6

There are also the "burn-down-the-house" ways of stopping an application:

Environment.Exit(int code);
Environment.FailFast(string message);
Thread.CurrentThread.Abort();
AppDomain.Unload(AppDomain.CurrentDomain);

For fun, here's another :)

[DllImport("kernel32.dll",SetLastError = true)]
static extern bool WriteProcessMemory(
      IntPtr hProcess, 
      IntPtr lpBaseAddress, 
      byte [] lpBuffer, 
      uint nSize, 
      out UIntPtr lpNumberOfBytesWritten);

var myProcess = Process.GetCurrentProcess();
var hProcess = myProcess.Handle;
var rnd = new Random();
while(true)
{
    var writeTo = new IntPtr((int)rnd.Next(0, int.MaxValue));
    var toWrite = new byte[1024];
    UIntPtr written;
    WriteProcessMemory(
        hProcess, 
        writeTo, 
        toWrite, 
        (uint)toWrite.Length, 
        out written);
}

Out of curiosity and prodding, let's take them for a test drive!

Our test rig:

    static void Main(string[] args)
    {
        Trace.Listeners.Add(new ConsoleTraceListener());
        AppDomain.CurrentDomain.UnhandledException += OnNoes;
        try
        {
            // INSERT BURN STATEMENT
            Foo();
        }
        catch (Exception e)
        {
            Bar();
        }
        finally
        {
            Baz();
        }
    }

    static void Foo()
    {
        Trace.WriteLine("I AM FOO!");
    }
    static void Bar()
    {
        Trace.WriteLine("I AM BAR!");
    }
    static void Baz()
    {
        Trace.WriteLine("I AM BAZ!");
    }
    static void OnNoes(object sender, UnhandledExceptionEventArgs e)
    {
        Trace.WriteLine("OhNoes!");
    }

The results!

The Burn Statement:

Thread.CurrentThread.Abort();

Output:

I AM BAR!
I AM BAZ!

The Burn Statement:

AppDomain.Unload(AppDomain.CurrentDomain);

Output:

I AM BAR!
I AM BAZ!

The Burn Statement:

Environment.Exit(-1);

Output:

Nothing! No trace output at all!

The Burn Statement:

Environment.FailFast("Burn!!!");

Output:

Application crash! A FatalExecutionEngineError was thrown, 
which was not caught by any block/handler. No trace output.

So there you go! What? I missed one?

The Burn Statement:

Splode();

Where "Splode" is:

    static void Splode()
    {
        var myProcess = Process.GetCurrentProcess();
        var hProcess = myProcess.Handle;
        var rnd = new Random();
        while (true)
        {
            var writeTo = new IntPtr((int)rnd.Next(0, int.MaxValue));
            var toWrite = new byte[1024];
            UIntPtr written;
            WriteProcessMemory(
                hProcess,
                writeTo,
                toWrite,
                (uint)toWrite.Length,
                out written);
        }            
    }

Output:

Application crash! A FatalExecutionEngineError was thrown, 
which was not caught by any block/handler. No trace output.
Crashed Visual Studio while running attached!
于 2013-03-07T00:12:10.583 に答える
5

はい...コメントで述べたように、最も明白なものは、、await/ yield break、、、yield returnなどです。ただし、これらのステートメント/式はすべて、ステートメントを含むメソッドで自分で作成する必要があるため、実際に心配する必要はありません。gotoif(false)try

ただし、これらとは別に、例外をスローしたり、リターンしたりせずに (またはこれら 2 つのメソッドのいずれかを実行せずに) 終了する方法がありますそれは… 例外ではないものを投げることです。

C# 言語仕様では、スローできるのは class のインスタンスExceptionまたはnullリテラル (この場合は aNullReferenceExceptionがスローされる) のみであると規定されています。§8.9.5 に記載されています。

[throw] 式は、クラス型 System.Exception、System.Exception から派生したクラス型、または有効な基本クラスとして System.Exception (またはそのサブクラス) を持つ型パラメーター型の値を示す必要があります。式の評価で null が生成された場合は、代わりに System.NullReferenceException がスローされます。

ただし、この制限は C# コードのみを制限します。C# コードは中間言語にコンパイルされますが、このような制限はありません。C# 言語仕様の §8.10 にも記載されています。

一部のプログラミング言語は、System.Exception から派生したオブジェクトとして表現できない例外をサポートする場合がありますが、そのような例外は C# コードでは生成できません。

これらの例外をキャッチするには、次のように一般的な catch 句を使用する必要があります。

try
{
    //...
    Foo();
}
catch
{
    Bar();
}

注: この方法は、バージョン 2.0 より前の .NET フレームワークにコンパイルする場合にのみ適用されます。そのバージョン以降、CLR はスローされたオブジェクトをRuntimeWrappedException. ありがとう、スヴィック!

さらに、他の何人かの人々は、プロセスを強制終了すること、または をスローすることについて言及しましたがStackOverflowException、どちらもこのタスクを達成するのにうまく機能します。これら以外にも方法があるかもしれませんが、私はそうは思いません (コンピューターのプラグを突然抜く以外は、天国ではありません)。-- ブランドン

于 2013-03-07T00:05:16.933 に答える
3

次のコードがあるとします。

try
{
    /*Breaking statement goes here*/

    Foo();
}
catch (Exception ex)
{
    Bar();
}
finally
{
    Baz();
}

ブレーカーを 3 つの一般的な理由に分けます。

  1. コード フロー ステートメント:

    1.1。return: ふー(-); バー(-); バズ(+);

    1.2. goto: ふー(-); バー(-); バズ(+);

    1.3。if(false): ふー(-); バー(-); バズ(+);

    1.4。while(true){}: ふー(-); バー(-); バズ(-);

    1.5。yield return、メソッドが IEnumerable を返しyield return、ブロックの前にある場合try: Foo(-); バー(-); バズ(-);

    1.6。yield break、メソッドが IEnumerable: Foo(-); を返す場合。バー(-); バズ(-);

    1.7。break、コードがサイクルでラップされている場合: Foo(-); バー(-); バズ(+);

    1.8。continue、コードがサイクルでラップされている場合: Foo(-); バー(-); バズ(+);

  2. プロセス/ドメイン/スレッドの終了。

    2.1. Process.GetCurrentProcess().Kill(): ふー(-); バー(-); バズ(-);

    2.2. Environment.Exit(0): ふー(-); バー(-); バズ(-);

    2.3. Environment.FailFast(""): ふー(-); バー(-); バズ(-);

    2.4. AppDomain.Unload(AppDomain.CurrentDomain): ふー(-); バー(+); バズ(+);

    2.5。Thread.CurrentThread.Abort(): ふー(-); バー(+); バズ(+);

  3. 未処理の例外。

    3.1. .NET 2.0 より前のアンマネージ コードの例外: Foo(-); バー(-); バズ(+);

    3.2. .NET 2.0 以降のアンマネージ コードの例外: Foo(-); バー(+); バズ(+);

    3.3. .NET 4.0 以降の破損したプロセス状態の例外 (<legacyCorruptedStateExceptionsPolicy>どちらHandleProcessCorruptedStateExceptionsAttributeも指定されていない): Foo(-); バー(-); バズ(+);

    3.4。.NET 4.0 より前の破損したプロセス状態の例外または<legacyCorruptedStateExceptionsPolicy>またはHandleProcessCorruptedStateExceptionsAttributeが指定されています: Foo(-); バー(+); バズ(+);

    3.5。.NET 2.0 以降の別のスレッドで例外が発生し、<legacyUnhandledExceptionPolicy>有効になっていません: Foo(-); バー(-); バズ(-);

    3.6. .NET 2.0 より前または<legacyUnhandledExceptionPolicy>有効になっている別のスレッドでの例外: Foo(+); バー(-); バズ(+);

于 2013-03-09T17:42:03.473 に答える
1

他にもいくつかのオプションがあります (The Daily WTF で言及された、ある企業はトランザクションがすべてをキャッチすると考えていました)。つまり、オペレーティング システムがシャットダウンし、タスクが強制終了され、マシンの電源が失われます (笑わないでください。 )。これらのいくつかは、たとえば Form_Closing イベント (OS のシャットダウン) を使用してきれいに処理できますが、できないものもあります。オペレーティング システムとその他のアプリケーション (たとえば、クラッシュしたときの VS) は、X 分ごとに一時的な状態を保持することで、これらの状況を回避します。その状態が存在する場合、アプリケーションは予期せず終了しました。そのような状態が存在しない場合、アプリケーションは正常に終了し、データは正しく保存されています。

于 2013-03-07T00:18:38.343 に答える