StackTrace を取得してる最中に AccessViolationException が出るから困る

問題があったときのスタックトレース

  1. FileSystemEntry.fromFileSystemEntry
  2. FileSystemEntry.getFileSystemEntry
  3. SecurityDescriptor#__constructor()
  4. SecurityDescriptor#_M_get_file_security
  5. AdvApi32.GetFileSecurity

で、StackTrace を取得してる最中に AccessViolationException が送出されるわけだね。
これをスルーしてると、あるとき StackOverflowException がでちゃうってのをどーにかしよーってわけ。

幸いにもCLR ランタイム変更点[microsoft.com] にそれっぽいのが…
なんてことはなかったぜ!

StackTrace 中に AccessViolationException が出る

StackTrace じゃなくて StackOverflowException が送出されたときには、スタックトレースが含まれていないから困る。
場合が場合だけにしょうがないんだろうけど。

Exception#StackTrace プロパティの中では、Environment.GetStackTrace() が呼ばれてて、その中で System.Diagnostics 名前空間の StackTrace オブジェクトが作成されてるみたい。 このオブジェクトは CaptureStackTrace(4) を呼びだして、そんでまず色々あって GetStackFramesInternal(3) を呼びだすんだけどメモリがたんねーとか NULL ポインタ入ってたとか何らかの原因で AccessViolationException を投げるんだよね。
この AccessViolationException ってのは:

安全でないマネージ コードで発生したアクセス違反は、プラットフォームに
応じて NullReferenceException または AccessViolationException として表現されます。

ってことらしい。
ネイティブの WIN32API を使ったクラスのメソッド内で例外を送出しまくるといつかはメモリエラーになるってことなんだろうか?*1
または、SecurityDescriptor クラス───中で Marshal.AllocHGlobal(1) を呼んでアンマネージメモリを
割り当てている───の中の IntPtr が適切に処理されていないのだろうか?*2

関係無いんだけど、Marshal.AllocHGlobal(1) は LocalAlloc(2) を呼んでるらしい。
Global って書いてあるから GlobalAlloc 使ってるのかと思ってた。

StackTrace ∋ StackFrame

集合の要素を表す場合には「∈」あるいは「∋」を用いる。

Aの集合の要素がaである場合
a ∈ A
あるいは
A ∋ a
のようにあらわす。

すたっくふれーむ は すたっくとれーす における 1 つの関数の呼び出しを表すんじゃないかな…。
最後のメソッドが ~Internal() だったことからっていうか AccessViolationException が送出されてることから丸わかりなんだけどさ…
「安全でないマネージコード」を使っていることは明白だ… ってのが分かってもしょうがないんだよね…(´・ω・`)

*1:そんなことはなかったぜ!!!

*2:そうだった