yotiky Tech Blog

とあるエンジニアの備忘録

Unity - UnityWebRequest で「A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details.」の例外が発生する時の対処

目次

環境

  • Unity 2021.3.29f1

起こった事象

LogをApplication Insightsに投げるアプリケーションで、
シーンを切り替えた時にたまに、UploadHandlerRawのコンストラクタで以下の例外が発生する。

A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details.

調査

ログに出力される内容は詳細が含まれていないため、設定を変更してスタックトレースが出るようにする。

Unity.Collections.NativeLeakDetection.Mode 
    = Unity.Collections.NativeLeakDetectionMode.EnabledWithStackTrace;

この設定は1回実行すると保存される(ローカルのEditor?)ようなので、実行後にコードを削除しても設定は維持される。元に戻す場合はEnabledを1回設定する。

Unity.Collections.NativeLeakDetection.Mode 
    = Unity.Collections.NativeLeakDetectionMode.Enabled;

スタックトレースを有効にした結果、UploadHandlerRawのコンストラクタで例外が発生していることが分かった。

A Native Collection has not been disposed, resulting in a memory leak. Allocated from: Unity.Collections.NativeArray`1:.ctor(Byte, Allocator) UnityEngine.Networking.UploadHandlerRaw:.ctor(Byte) (省略)

原因

関連してそうな記事。Unity 2021 から発生するようになったっぽい。

forum.unity.com

qiita.com

対処

記事を参考に、明示的にDisposeを呼び出したり、usingで囲ってみたり、Try-catchしてみたりしたが、依然として例外は発生するため、GameObject の Destroy でDisposeしてやることで今のところはおさまっているように見える。

private UploadHandlerRaw uh;

private IEnumerator SendTelemetryRequest(byte[] data = null)
{
    using (UnityWebRequest www = new UnityWebRequest(url))
    {
        uh = new UploadHandlerRaw(data);
        www.method = UnityWebRequest.kHttpVerbPOST;
        www.downloadHandler = new DownloadHandlerBuffer();
        www.chunkedTransfer = false;
        www.uploadHandler = uh;
        www.SetRequestHeader("Content-Type", "application/json");

        yield return www.SendWebRequest();

        // 処理省略

        uh.Dispose();
        uh = null;
    }
]

private void OnDestroy()
{
    if (uh != null)
    {
        uh.Dispose();
        uh = null;
    }
}