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

김재섭·2022년 10월 7일
1
post-thumbnail

_

발단

A Native Collection has not been disposed, resulting in a memory leak.
라는 빨간줄 에러가 마구마구 뜬다.

UnityWebRequest를 쓸 때, Get에서는 안뜨는데 Post에서는 뜨는 오류였다.
(유니티 버전은 2021.3.1f1)

게다가 Post 할때마다 항상 뜨는것도 아니었다.
여러번 Post하거나, 특히 짧은시간에 여러번 보내면 저 오류가 많이떴다.

console에 뜨는 로그를 눌러도 따로 뜨는 말도없고, stackTrace를 Full로 놓아도 뜨는게 없다.

구글링을 정말 열심히 했지만...저 에러를 검색하면 가장 많이 하는 말이 request.Dispose()를 안해서 그렇다고 한다. 하지만 using문을 쓰면 dispose가 자동으로 되는걸...

_

전개

아래는 문제를 일으켰던 코드다.


    private IEnumerator SendPost(string url, string parameter, Action<string> callback)
    {

        using (UnityWebRequest request = UnityWebRequest.Post(url, parameter))
        {
            byte[] jsonToSend = new UTF8Encoding().GetBytes(parameter);

            request.uploadHandler = new UploadHandlerRaw(jsonToSend);
            request.SetRequestHeader("Content-Type", "application/json");

            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success)
            {

                callback(request.downloadHandler.text.Replace('{', ' ').Replace('}', ' ').Replace('"', ' '));
            }
            else
            {
                callback("Error");
            }
        }
    }

여기에서 request.uploadHandler = new UploadHandlerRaw(jsonToSend);
이녀석이 문제였다.

1.애초에 using문에서 post를 선언할때를 보면 url과 uploadHandler를 넣어주게 되는데, 이미 UploadHandler는 이미 이때 생성이 된것이다.

2.그리고 using문 안에서 UploadHandlerRaw를 사용해서 parameter를 인코딩후에 uploadHandler에 넣어주게 되는데,,,

쉽게 말하면 1번과 2번에서 중복해서 uploadHandler를 건드려서 A Native Collection has not been disposed 이라는 에러가 난 것 으로 보인다.
그래서 get에서는 안뜨고 uploadHandler를 건드리는 Post에서만 떴던것이다!

_

절정

UnityWebRequest 의 디폴트 설정으로, uploadHandler는 request가 dispose 된 이후에 자동으로 같이 dispose 되도록 되어있다.

하지만 그게 문제가 아니라 중복으로 값이 들어가는게 문제였기 때문에,,,
단순하게 인코딩하기 "전에" 구문 윗줄에 uploadHandler를 한번 dispose 해줬다.

   private IEnumerator SendPost(string url, string parameter, Action<string> callback)
    {
        using (UnityWebRequest request = UnityWebRequest.Post(url, parameter))
        {
            byte[] jsonToSend = new UTF8Encoding().GetBytes(parameter);

            request.uploadHandler.Dispose();
            request.uploadHandler = new UploadHandlerRaw(jsonToSend);
            request.SetRequestHeader("Content-Type", "application/json");

            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success)
            {

                callback(request.downloadHandler.text.Replace('{', ' ').Replace('}', ' ').Replace('"', ' '));
            }
            else
            {
                callback("Error");
            }
        }
    }

_

결말

오랜 시간 앉아서 고민했고, 코드 단 한줄 작성으로 문제가 해결되었다.

사람한테 마약이 왜 필요한걸까?
코딩하면 되는데

profile
Unity C#

3개의 댓글

comment-user-thumbnail
2023년 1월 2일

와우~ 저도 이 문제 때문에 엄청 고생했었는데 이 방법대로 하니까 바로 해결됐네요~
이걸 찾아내시다니 대단하십니다!

1개의 답글
comment-user-thumbnail
2023년 4월 7일

저도 한참 헤매다가 이 포스트 덕에 해결했습니다 감사합니다~

답글 달기