はまったこと
今日の記事は先日起こった問題を覚書として記録しておきます。 ちなみにまだちゃんとした原因は分かっておらず、逃げの対策をとってる状態です。
今作成しているPluginで、C++でもBlueprintでも関数をオーバーライドしたいなあと思って色んな ところで下のようなパターンを実装してました。
UFUNCTION(BlueprintNativeEvent, Category = "ObjectDeliverer")
void Start();
virtual void Start_Implementation();
上記の例ではC++の別のクラスからStart()が呼ばれる想定です。
このクラスを継承したC++のクラスではStart_Implementation()をオーバーライドして、BlueprintではStart()をオーバーライドする事でどっちでクラスを継承してもOKだよってのを狙ってました。
実装して動かしてみるとしばらくはちゃんと動いているように見えていたのですが、ちょいちょいStart()を呼ぶタイミングで落ちることに気づきました。
うーん、このProcessEventのIsUnreachableにひっかかって落ちる問題なんだ?
— ayuma (@ayuma_x) January 29, 2019
BlueprintNativeEventの関数使っているところが該当するってことはわかったんだけど、どう直したらよいのか不明だ。
デバッグして追ってみると、Start()の中ではProcessEventが呼ばれておりリフレクションで関数は実行されてるって事が分かりました。
その中のcheck(!IsUnreachable)で落ちているって事は分かったのですがなぜそうなっているのか全く分かりません。
IsUnreachableってことはGC対象になってしまったのか???と思いコードをチェックしたのですが、ちゃんとUPROPERTY()で指定した変数で保持してます。
一応念のため、別のアプローチもとってみようと思い、下の記事の内容も試してみましたが現象は変わりませんでした。
UPROPERTY を使わずにオブジェクトをガーベジ コレクションの対象から外す方法 - Qiita
BlueprintNativeEventを使っているところでも2通りのタイミングで落ちていて、起動後しばらくしたら落ちる箇所と、BeginDestroy時がありました。
BeginDestroyはまだ終了時なのでここじゃこういった関数呼び出しはしちゃいけないのかなと思って、何となく理解できるのですがもう一つのパターンが分かりません。
ただちょっと普通じゃないのはFRunnableThreadを使って走らせているワーカースレッド内で落ちるのでその辺りも関係しているのかなとも思ったり。
結局原因が分からず直し方も分からないという情けない結論に至ったため、Blueprintでのオーバーライドは諦めてBlueprintNativeEventを外し通常のvirtual関数にしました。
その後は全く落ちなくなったのでとりあえずは良いのですが、モヤモヤしてるのでちゃんと時間をとってどこかで調べたいと思ってます。
その後落ちないって事はGCで回収されてないって事なので余計によくわからない。。。