---
# System prepended metadata

title: C# .NET Framework 4.5.2 AccessViolationException によりアプリが落ちる　2021-05-14
tags: [AccessViolationException, C#, .NET Framework 4.5.2]

---

---
lang: ja-jp
breaks: true
---
# C# .NET Framework 4.5.2 AccessViolationException によりアプリが落ちる　2021-05-14

> AccessViolationExceptionを捕捉できるようにする
> https://blog.xin9le.net/entry/2015/07/22/053738

## AccessViolationExceptionを捕捉する

### `[HandleProcessCorruptedStateExceptions]`を、補足したいメソッドの属性に設定するか、App.configに`<legacyCorruptedStateExceptionsPolicy enabled="true" />`を追加する。

## 以下検証

### C++側

#### Dll2.cpp
```cpp=
// Dll2.cpp : DLL 用にエクスポートされる関数を定義します。
//

#include "pch.h"
#include "framework.h"
#include "Dll2.h"
#include <iostream>


void Test()
{
	std::cout << "Cの関数 Test() が呼び出されました。" << std::endl;

	// ここでわざと不正なメモリ参照エラーを出す。
	const char *ptr = 0;
	std::cout << ptr;
}

void Test_OK()
{
	std::cout << "Cの関数 Test_OK() が呼び出されました。" << std::endl;

	const char *ptr = "aaaaaaaaaaaaa";
	std::cout << ptr;
}
```

#### Dll2.h
```cpp=
// 以下の ifdef ブロックは、DLL からのエクスポートを容易にするマクロを作成するための
// 一般的な方法です。この DLL 内のすべてのファイルは、コマンド ラインで定義された DLL2_EXPORTS
// シンボルを使用してコンパイルされます。このシンボルは、この DLL を使用するプロジェクトでは定義できません。
// ソースファイルがこのファイルを含んでいる他のプロジェクトは、
// DLL2_API 関数を DLL からインポートされたと見なすのに対し、この DLL は、このマクロで定義された
// シンボルをエクスポートされたと見なします。
#ifdef DLL2_EXPORTS
#define DLL2_API __declspec(dllexport)
#else
#define DLL2_API __declspec(dllimport)
#endif

extern "C"
{
	__declspec(dllexport) void Test();
	__declspec(dllexport) void Test_OK();
}
```

### C#側

#### Program.cs
```csharp=
        [DllImport("DLL2.dll")]
        static extern void Test();

        [DllImport("DLL2.dll")]
        static extern void Test_OK();

        //[HandleProcessCorruptedStateExceptions]
        static void Main(string[] args)
        {
            try
            {
                Test();
            }
            catch (Exception ex)
            {
                if (ex is AccessViolationException)
                {
                    Console.WriteLine("AccessViolationException！！");
                }
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }

            Test_OK();

            Console.WriteLine("処理完了！！");
            Console.ReadLine();
        }
```

#### App.config
```xml=
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>

  <runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true" />
  </runtime>

</configuration>
```

### 実行結果

![](https://i.imgur.com/H4wiqsI.png)


### `AppDomain.CurrentDomain.UnhandledException`での補足も可能。

`<legacyCorruptedStateExceptionsPolicy enabled="true" />`を設定することで、`UnhandledException`での補足も可能。

```csharp=
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

～・・・～

        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is Exception)
            {
                Exception ex = e.ExceptionObject as Exception;
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
            else
            {
                Console.WriteLine(e.ToString());
            }
        }

```

###### tags: `C#` `.NET Framework 4.5.2` `AccessViolationException`
