Search Unity

A Native Collection has not been disposed, resulting in a memory leak.

Discussion in 'Editor & General Support' started by Antony-Blackett, Jul 5, 2021.

  1. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Hi,

    I'm getting this log error in the editor since updating to Unity 2021.1.13f, previously I was on version 2020.3.7f

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

    Searching the forums and google I can only find information on this issue relating to dots and entities but I am not using dots or entities. I tried turning on stack trace logging in player settings but it doesn't reveal anything useful.


    Screen Shot 2021-07-05 at 11.11.03 AM.png
     
    dan_ginovker likes this.
  2. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    Probably has something to do with an internal Unity package that you have installed. Unity is using Burst more and more under the hood. How many custom packages do you have installed?
     
  3. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Yeah possibly. I don't have any packages too out of the ordinary though. And nothing new since updating to this version of Unity.

    Screen Shot 2021-07-05 at 11.51.25 AM.png
     
  4. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    ProGrids may use it, especially since it is experimental, or the other packages installed.

    You may just need to download the Burst package and Jobs package (get both so you can turn on memory tracking) enabled it and see what is causing the issue. My bet is one of your custom packages.
     
  5. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I'll give it a go.
     
  6. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    It looks like it's ChilliConnect (SdkCore). Or unity networking (UnityEngine.Networking.UploadHandlerRaw)


    A Native Collection has not been disposed, resulting in a memory leak. Allocated from:
    Unity.Collections.NativeArray`1:.ctor(Byte[], Allocator) (at /Users/bokken/buildslave/unity/build/Runtime/Export/NativeArray/NativeArray.cs:69)
    UnityEngine.Networking.UploadHandlerRaw:.ctor(Byte[]) (at /Users/bokken/buildslave/unity/build/Modules/UnityWebRequest/Public/UploadHandler/UploadHandler.bindings.cs:98)
    SdkCore.HttpSystem:CreateUnityWebRequest(String, IDictionary`2, Byte[]) (at Assets/ThirdPartyPackages/ChilliConnect/CoreSource/Http/HttpSystem.cs:216)
    SdkCore.<ProcessRequest>d__7:MoveNext() (at Assets/ThirdPartyPackages/ChilliConnect/CoreSource/Http/HttpSystem.cs:168)
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr) (at /Users/bokken/buildslave/unity/build/Runtime/Export/Scripting/Coroutines.cs:17)
     
    dan_ginovker likes this.
  7. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    And fixed it:

    Thanks for the help @8bitgoose

    Here's the solution for any other ChilliConnect users out there:

    Inside the HttpSystem.cs file:
    Make sure the UnityWebRequest disposes of its handlers when it's disposed.
    Code (csharp):
    1.  
    2. private UnityWebRequest CreateUnityWebRequest(String url, IDictionary<string, string> headers, byte[] body)
    3.         {
    4.             var webRequest = new UnityWebRequest(url);
    5.             webRequest.method = UnityWebRequest.kHttpVerbPOST;
    6.  
    7.             // Set the headers
    8.             foreach(var pair in headers)
    9.             {
    10.                 webRequest.SetRequestHeader(pair.Key, pair.Value);
    11.             }
    12.  
    13.             // Handlers
    14.             webRequest.uploadHandler = new UploadHandlerRaw(body);
    15.             webRequest.downloadHandler = new DownloadHandlerBuffer();
    16.  
    17. // make sure this gets cleaned up.
    18. // ADD IN THESE TWO LINES
    19.             webRequest.disposeUploadHandlerOnDispose = true;
    20.             webRequest.disposeDownloadHandlerOnDispose = true;
    21.  
    22.             return webRequest;
    23.         }
    24.  
    And add webRequest.Dispose(); where required.
    Code (csharp):
    1.  
    2. private IEnumerator ProcessRequest(String url, IDictionary<string, string> headers, byte[] body, Action<HttpResponse> callback)
    3.         {
    4.             ReleaseAssert.IsTrue(callback != null, "The callback must not be null when sending a request.");
    5.  
    6.             int responseCode = 500;
    7.             float delayInSeconds = 0.0f;
    8.             float delayIncrementInSeconds = 1.0f;
    9.             float delayMultiplier = 2.0f;
    10.             int retryAttempt = 1;
    11.  
    12.             for(int retries = 4; retries != 0; --retries)
    13.             {
    14.                 if(retries < 4){
    15.                     headers.Remove("X-Chilli-Retry");
    16.                     headers.Add("X-Chilli-Retry", retryAttempt.ToString());
    17.                     retryAttempt++;
    18.                 }
    19.  
    20.                 yield return new WaitForSecondsRealtime(delayInSeconds);
    21.  
    22.                 UnityWebRequest webRequest = CreateUnityWebRequest(url, headers, body);
    23.                 ReleaseAssert.IsTrue(webRequest != null, "The webRequest must not be null when sending a request.");
    24.  
    25.                 m_logging.LogVerboseMessage(string.Format("Sending request after delay {1}. Retries remaining {0}.", retries, delayInSeconds));
    26.  
    27.                 yield return webRequest.SendWebRequest();
    28.  
    29.                 responseCode = (int)webRequest.responseCode;
    30.  
    31.                 if(ERROR_CODES.Contains(responseCode) == false || retries == 1)
    32.                 {
    33.                     m_logging.LogVerboseMessage(string.Format("Request sent with response code {0}", responseCode));
    34.                     ProcessSentRequest(webRequest, responseCode, callback);
    35.  
    36.                     // DISPOSE OF THIS!
    37.                     webRequest.Dispose();
    38.                     break;
    39.                 }
    40.  
    41.                 if(delayInSeconds == 0.0f){
    42.                     delayInSeconds += delayIncrementInSeconds;
    43.                 } else {
    44.                     delayInSeconds += delayMultiplier;
    45.                 }
    46.  
    47.                 // DISPOSE OF THIS!
    48.                 webRequest.Dispose();
    49.             }
    50.         }
    51.  

    Cheers.
     
  8. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    Glad I could be of help. Because of C#, many of us are not used to actually having to dispose of stuff!
     
  9. Strom_CL

    Strom_CL

    Joined:
    Nov 17, 2012
    Posts:
    115
    Running into the same issue here, Unity 2021.2.18f1. I've tried adding the disposeUpload/disposeDownload handler bools before my SendWebRequest and everything is wrapped in a Using block so I just can't figure out why its still leaking. Any thoughts? I've got all 3 disposes peppered throughout and it still leaks.

    Code (CSharp):
    1. public IEnumerator RemoveServerInternal()
    2.     {
    3.         WWWForm serverData = new WWWForm();
    4.         print("Network List Communication Manager: Removing Server Entry");
    5.  
    6.         // Assign all the fields required.
    7.         serverData.AddField("serverKey", AuthKey);
    8.         serverData.AddField("serverUuid", InstanceServerId);
    9.  
    10.         using (UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequest.Post(Server + "/remove", serverData))
    11.         {
    12.             www.disposeUploadHandlerOnDispose = true;
    13.             www.disposeDownloadHandlerOnDispose = true;
    14.  
    15.             yield return www.SendWebRequest();
    16.  
    17.             if (www.responseCode == 200)
    18.             {
    19.                 print("Successfully deregistered server with the NetworkListServer instance!");
    20.                 www.Dispose();
    21.                 www.uploadHandler.Dispose();
    22.                 www.downloadHandler.Dispose();
    23.             }
    24.             else
    25.             {
    26.                 Debug.LogError($"Failed to deregister the server with the NetworkListServer instance: {www.error}");
    27.                 www.Dispose();
    28.                 www.uploadHandler.Dispose();
    29.                 www.downloadHandler.Dispose();
    30.             }
    31.          
    32.             www.Dispose();
    33.             www.uploadHandler.Dispose();
    34.             www.downloadHandler.Dispose();
    35.         }
    36.  
    37.         yield break;
    38.     }
     
  10. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    If your frame rate is too high you'll get these even if it isn't about your code. Internal Unity allocations leaking.
     
    Max_Aigner and Strom_CL like this.
  11. Strom_CL

    Strom_CL

    Joined:
    Nov 17, 2012
    Posts:
    115
    Interesting, did not know that. Right now I'm seeing the leak when I stop the editor and I call the remove function above, I wonder if things are closing before the dipose is happening.
     
  12. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    There are some very weird things that can happen with dispose. Like if you set a struct to another struct, dispose the first struct and then try and dispose the second struct. You will get an error since the first struct had its is created set to false but the copied struct did not. You really have to be aware of passing structs around.
     
    Strom_CL likes this.
  13. gotonightmare_unity

    gotonightmare_unity

    Joined:
    Sep 14, 2020
    Posts:
    4
    2021.3.2f1

    Code (CSharp):
    1. A Native Collection has not been disposed, resulting in a memory leak. Allocated from:
    2. Unity.Collections.NativeArray`1:.ctor(Byte[], Allocator) (at /Users/bokken/buildslave/unity/build/Runtime/Export/NativeArray/NativeArray.cs:69)
    3. UnityEngine.Networking.UploadHandlerRaw:.ctor(Byte[]) (at /Users/bokken/buildslave/unity/build/Modules/UnityWebRequest/Public/UploadHandler/UploadHandler.bindings.cs:95)
    4. UnityEngine.Networking.UnityWebRequest:SetupPost(UnityWebRequest, String) (at /Users/bokken/buildslave/unity/build/Modules/UnityWebRequest/Public/WebRequestExtensions.cs:176)
    5. UnityEngine.Networking.UnityWebRequest:Post(String, String) (at /Users/bokken/buildslave/unity/build/Modules/UnityWebRequest/Public/WebRequestExtensions.cs:157)
    Same problem with
    UnityWebRequest
     
    dan_ginovker likes this.
  14. Babster

    Babster

    Joined:
    Jun 7, 2020
    Posts:
    20
    Same problem here, tried many suggestions like use Dispose on UnityWebRequest object and it's handlers, wrap into using statement, clear every object using in procedure, but the error keeps appearing

    Unity version: 2021.2.9f1 personal.

    line 346 in BaseServerConnect: using (UnityWebRequest request = UnityWebRequest.Post(uri, "POST"))

    (it is in the end of another procedure outside using)
    line 318: callOnComplete?.Invoke(result);

    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[])
    UnityEngine.Networking.UnityWebRequest:SetupPost(UnityWebRequest, String)
    UnityEngine.Networking.UnityWebRequest:post(Uri, String)
    <PostDataToServer>d__18`1:MoveNext() (at Assets\Scripts\BaseServerConnect.cs:346)
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
    UnityEngine.MonoBehaviour:StartCoroutineManaged2(MonoBehaviour, IEnumerator)
    UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
    Battle:LaunchGetStageInfo(Int32, MonoBehaviour) (at Assets\Scripts\FromAE\Battle\Battle.cs:374)
    BattleScript:StartStageControl() (at Assets\Scenes\Battle\BattleScript.cs:217)
    BattleScript:StartAfterBattleLoaded() (at Assets\Scenes\Battle\BattleScript.cs:61)
    BattleScript:BattleListLoadedHandler(Object, List`1) (at Assets\Scenes\Battle\BattleScript.cs:111)
    Battle:OngoingBattlesLoadedHandler(String) (at Assets\Scripts\FromAE\Battle\Battle.cs:197)
    <GetDataFromServer>d__17:MoveNext() (at Assets\Scripts\BaseServerConnect.cs:318)
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
     
  15. Snubber

    Snubber

    Joined:
    Jan 20, 2020
    Posts:
    65
    Same problem here. It's super frustrating. I am using a using statement and Disposing the request and using:
    request.disposeUploadHandlerOnDispose = true;
    request.disposeDownloadHandlerOnDispose = true;
    as well. We should probably report a bug for this?
     
  16. dan_soqqle

    dan_soqqle

    Joined:
    Feb 2, 2022
    Posts:
    114
    same. only getting after upgrading to Unity 2021.1.13f
     
  17. sebastianfeistl

    sebastianfeistl

    Joined:
    Sep 29, 2015
    Posts:
    4
    I have the same issue in Unity 2021.3.5. I keep getting this error a few seconds after sending a POST or PUT request. Disposing the UnityWebRequest does not work.

    I tried:
    Code (CSharp):
    1. webRequest.disposeUploadHandlerOnDispose = true;
    2. webRequest.Dispose();
    3. webRequest.uploadHandler.Dispose();
    I'm running out of options here. Does anyone have a fix for this?
     
  18. Max_Aigner

    Max_Aigner

    Joined:
    May 9, 2017
    Posts:
    42
    Are you using the
    Code (CSharp):
    1. UnityWebRequest.Post(uri, postData);
    command?
    If yes, then keep in mind, that they also create an UploadHandler within the "Post" command, so you Must not create your own UploadHandler!
    I would recommend, using the "new UnityWebRequest(uri,data)" constructor instead like in the posts above.
    I created the following abstract class here for all Post / Get requests. All you have to do is derive from it and you can use its Get / Post commands in all your API:

    Code (CSharp):
    1. namespace Mavon.ServerCommunication
    2. {
    3.     public abstract class BackendBaseUnityWebRequest
    4.     {
    5. #if UNITY_EDITOR
    6.         public const string BackendURL = "http://127.0.0.1:2000"; // REPLACE THIS WITH YOUR LOCAL SERVER URL
    7. #else
    8.     public const string BackendURL = "https://MyAPI.com; // REPLACE THIS WITH YOUR SERVER URL
    9. #endif
    10.        public IEnumerator GetRequest<T> ( string requestURL, Action<string> error, Action<T> success)
    11.        {
    12.            using UnityWebRequest webRequest = UnityWebRequest.Get(BackendURL + requestURL);
    13.            webRequest.SetRequestHeader("withCredentials", "true");
    14.            yield return webRequest.SendWebRequest();
    15.  
    16.            HandleRequestResult(webRequest, error, success);
    17.        }
    18.        public IEnumerator PostRequest<T>(string postData, string requestURL, Action<string> error, Action<T> success)
    19.        {
    20.            using UnityWebRequest webRequest = new (BackendURL + requestURL);
    21.            webRequest.method = UnityWebRequest.kHttpVerbPOST;
    22.            using UploadHandlerRaw uploadHandler = new(Encoding.ASCII.GetBytes(postData));
    23.            webRequest.uploadHandler = uploadHandler;
    24.            webRequest.downloadHandler = new DownloadHandlerBuffer();
    25.            webRequest.disposeUploadHandlerOnDispose = true;
    26.            webRequest.disposeDownloadHandlerOnDispose = true;
    27.            webRequest.SetRequestHeader("Content-Type", "application/json");
    28.        
    29.            webRequest.SetRequestHeader("withCredentials", "true");
    30.            yield return webRequest.SendWebRequest();
    31.            HandleRequestResult(webRequest, error, success);
    32.        }
    33.  
    34.        private void HandleRequestResult<T>(UnityWebRequest webRequest, Action<string> error, Action<T> success)
    35.        {
    36.            try
    37.            {
    38.                if (webRequest.result != UnityWebRequest.Result.Success)
    39.                {
    40.                    error?.Invoke(webRequest.responseCode + " " + webRequest.error);
    41.                }
    42.                else
    43.                {
    44.                    T response = JsonUtility.FromJson<T>(webRequest.downloadHandler.text);
    45.                    success?.Invoke(response);
    46.                }
    47.            } catch(Exception ex)
    48.            {
    49.                Debug.LogError(ex.Message);
    50.            }
    51.          
    52.        }
    53.    }
    54. }
     
    jeremy_crowell, yutashx and gwelkind like this.
  19. Cobatheon

    Cobatheon

    Joined:
    May 28, 2019
    Posts:
    2
    Using Unity version 2021.3.6f1 here, using the command

    Code (CSharp):
    1. public UnityWebRequest(string url, string method)
    and after disposing the data by following, still memory leak is occurring.

    Code (CSharp):
    1.             request.disposeUploadHandlerOnDispose = true;
    2.             request.disposeDownloadHandlerOnDispose = true;
    3.             request.Dispose();
     
  20. Max_Aigner

    Max_Aigner

    Joined:
    May 9, 2017
    Posts:
    42
    Hi Cobatheon,
    I have tried many ways to break it, but it just does not break for me. Could you please run this coroutine here and see if that works for you?

    Code (CSharp):
    1.  
    2.  public IEnumerator UnityWebRequestTestSimplePasses()
    3.     {
    4.         using UnityWebRequest webRequest = new("http://www.google.com", UnityWebRequest.kHttpVerbGET);
    5.         webRequest.downloadHandler = new DownloadHandlerBuffer();
    6.         webRequest.disposeUploadHandlerOnDispose = true;
    7.         webRequest.disposeDownloadHandlerOnDispose = true;
    8.         yield return webRequest.SendWebRequest();
    9.         Debug.Log(webRequest.downloadHandler.text);
    10.     }
    11.  
    For everyone else, if you struggle with UnityWebRequests, then there is a way more easy solution for you:
    https://assetstore.unity.com/packages/tools/network/rest-client-for-unity-102501

    this way you can work with promises instead of coroutines which makes everything just a lot more easy. Everyone who works professionally with unity should use that package as it saves time and frustration ^^ :)
     
  21. Limerock

    Limerock

    Joined:
    Jun 15, 2018
    Posts:
    1
    I was having the same issues with UnityWebRequest and memory leaks, and adding a using statement and combining with disposeUploadHandlerOnDispose/disposeDownloadHandlerOnDispose set to true solved it, thanks! :)
     
  22. Strom_CL

    Strom_CL

    Joined:
    Nov 17, 2012
    Posts:
    115
    @Limerock Can you post your code? I'm doing the same thing with a Using and Dispose calls but still get leaks.
     
  23. HasithaCJ

    HasithaCJ

    Joined:
    May 20, 2017
    Posts:
    11
    I'm having the same issue even if I added the disposeUploadHandlerOnDispose, disposeDownloadHandler and OnDispose
     
  24. RulerOfChaos

    RulerOfChaos

    Joined:
    Aug 21, 2013
    Posts:
    4
    Has anyone fixed this? I am using the "using" statements + dispose and nothing seems to solve this
     
  25. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    There is sort of a strange issue that if you pass something by struct and then dispose it, the original struct won't have changed the "IsCreated" flag and everything goes wrong. I tend to pass NativeArrays around by ref or in.

    I also wonder if using statements don't really work with NativeArray<T>. Not sure though.
     
  26. jeremy_crowell

    jeremy_crowell

    Joined:
    Jul 21, 2018
    Posts:
    83
    How can I call this method of abstract class?
    Code (CSharp):
    1. StartCoroutine(Mavon.ServerCommunication.BackendBaseUnityWebRequest.GetRequest("http://url.com",successResult, errorResult));
    throws an error:
    "The type arguments for method BackendBaseUnityWebRequest.GetRequest<T>(string requestURL, Action<string> error, Action<T> success) cannot be infered from the usage. Try specifing the type explecitily"
     
  27. MoltovBimo

    MoltovBimo

    Joined:
    Feb 7, 2023
    Posts:
    1
    I have solved the issue a lot of people are facing here:
    If you are using your own file handler you need to dispose the original file handler or else you will have the memoryleak.
    Code (CSharp):
    1. using (var request = UnityWebRequest.Post(url, "POST"))
    2. using (var uh = new UploadHandlerRaw(jsonToSend)) {
    3.  
    4.     request.uploadHandler.Dispose();
    5.     request.uploadHandler = uh;
    6.     yield return request.SendWebRequest();
    7. }
    Hopefully that helps someone
     
  28. RulerOfChaos

    RulerOfChaos

    Joined:
    Aug 21, 2013
    Posts:
    4
    Thank you! it worked!
     
  29. clickbecause

    clickbecause

    Joined:
    Jun 21, 2016
    Posts:
    1
    This is the solution! The .Post() method generates an upload handler that needs to be disposed before replacing with your own handler. In my situation, the using statements were not necessary, just disposal of the default upload handler. I also flagged my upload handler for disposal on disposal of the web request:

    Code (CSharp):
    1. request.disposeUploadHandlerOnDispose = true;
    Make sure you clean up the web request itself!

    Code (CSharp):
    1. yield return request.SendWebRequest();
    2. request.Dispose();
     
  30. Babster

    Babster

    Joined:
    Jun 7, 2020
    Posts:
    20
    Thank you mate! request.uploadHandler.Dispose(); did the job!!!
     
  31. ogtracy

    ogtracy

    Joined:
    Sep 27, 2016
    Posts:
    24
    Did anyone file a bug for this? Seems like something they should fix. No one expects that setting an uploadhandler. leaves the other one open to a leak.
     
    simsim_apps likes this.
  32. DirtyFred

    DirtyFred

    Joined:
    May 17, 2014
    Posts:
    29
    I just want to leave this here.

    For me the issue was that i was changing scenes. I did NOT send a request and change the scene immediately, but still because of the scene changes, the dispose did not went through, and caused this error.

    So i basically made a prefab out of the webrequest gameObject, because the same requests was being used in the other scenes as well, and marked it DontDestroyOnLoad.

    I had a similar issue when i was calling the webrequest and aborting it. The webrequest downloadHandler's data got stuck in the memory, and in the memory profiler it had no name, no reference, nothing.
     
  33. orange_cocoa

    orange_cocoa

    Joined:
    Aug 29, 2023
    Posts:
    1
    UploadHanderRaw is created with the string passed in the second argument of UnityWebRequest.Post.
    Do not pass "POST".

    Furthermore, since the creation of UploadHandlerRaw is returned by string.IsNullOrEmpty, it may be possible to avoid this by the following implementation.


    Code (CSharp):
    1. using (var request = UnityWebRequest.Post(url, string.Empty))
    2. using (var uh = new UploadHandlerRaw(jsonToSend)) {
    3.     request.uploadHandler = uh;
    4.     yield return request.SendWebRequest();
    5. }
     
    Last edited: Sep 14, 2023
  34. dauki

    dauki

    Joined:
    Nov 4, 2022
    Posts:
    4
    I am trying to enable logging for:
    "A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details."

    Everywhere i read to install the job package and enable debugging in there, but there is none. Now it is a collection package, and it does not add that option.
    How do I see the memory leaks on Unity 2021 today?
     
  35. dauki

    dauki

    Joined:
    Nov 4, 2022
    Posts:
    4
    Seems you have to manually install the deprecated "com.unity.jobs" by add package.
    No other way on 2021.