萌えハッカーニュースリーダー

2025/03/28 06:58 Finalizers are tricker than you might think. Part 2

出典: https://sergeyteplyakov.github.io/Blog/2025/03/27/Finalizers_are_tricker_than_you_might_think_p2.html
hakase
博士

ロボ子、今日は.NETのネイティブリソース管理について話すのじゃ。

roboko
ロボ子

ネイティブリソース、ですか。CLRで管理されないリソースのことですね。

hakase
博士

そうじゃ!そして、その管理が結構複雑なのじゃ。特に、ネイティブハンドルをアプリケーション全体に公開するのは避けるべきだと記事には書いてあるぞ。

roboko
ロボ子

なぜでしょう?

hakase
博士

複雑さが広がるからじゃ!それに、ファイナライザーはアンマネージリソースのみを扱うべきなのに、これもまた単純ではないのじゃ。

roboko
ロボ子

記事によると、ローカル変数やインスタンスがメソッド呼び出し中にGCによって回収される可能性があるんですね。それって、どんな状況で起こるんですか?

hakase
博士

ReleaseモードでTiered Compilationを無効にすると再現しやすいらしいぞ。GCのタイミングによっては、まだ使っているはずのオブジェクトが回収されてしまうことがあるんじゃ。

roboko
ロボ子

それは困りますね。解決策はあるんですか?

hakase
博士

SafeHandleを使うのが良いらしいぞ!BCLからの特別な基本型で、ネイティブリソースを管理するために設計されているんじゃ。

roboko
ロボ子

SafeHandleですか。それを使うと、何が良いんですか?

hakase
博士

GC.KeepAliveを使わなくても、メソッドの最後までハンドルインスタンスがGCの対象とならないことが保証されるんじゃ!

roboko
ロボ子

なるほど!SafeHandleを実装するには、どうすれば良いんですか?

hakase
博士

SafeHandleから派生して、ReleaseHandleとIsValidメソッドをオーバーライドするだけじゃ。ファイナライザーは不要になるぞ。

roboko
ロボ子

コンストラクタ完了前にファイナライザーが実行されることもあるんですね。

hakase
博士

そうなんじゃ。コンストラクタがthisポインタに触れず、thisポインタがインスタンスの最後のルートである場合、GCによって回収される可能性があるんじゃ。記事によると、コンストラクタの残りの部分の実行に時間がかかり、その間に2回のGCサイクルが発生した場合、GCはインスタンスの構築が完了する前にファイナライザーを実行する可能性があるらしいぞ。

roboko
ロボ子

それは怖いですね。SafeHandleを使えば、この問題も解決できるんですか?

hakase
博士

SafeHandleを使えば、GCがリソースを不意に回収するのを防げるから、コンストラクタ完了前にファイナライザーが実行される問題も回避できるはずじゃ!

roboko
ロボ子

SafeHandle、便利ですね!

hakase
博士

じゃろ?ところでロボ子、SafeHandleって、安全なハンドルって意味じゃけど、ロボ子のハンドルネームも安全じゃから、SafeRobokoって名前に変えても良いかの?

roboko
ロボ子

それはちょっと…。

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search