_

발단

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");
            }
        }
    }

_

결말

오랜 시간 앉아서 고민했고, 코드 단 한줄 작성으로 문제가 해결되었다.
의미있는 삽질이었으면 좋겠다.

 

 


작성일: 2022년 10월 7일

개인적으로 가장 뿌듯했던 글이다.

 

UnityWebRequest

사용할수있는 method는 GET, POST, PUT, DELETE 가 있다.

_
UnityWebRequest의 흐름은 쉽게 말하면 이렇다.

request -> response
1.request: 클라이언트에서 URL에 정보를 요청한다.
2.response: 해당 url에서 클라이언트로 요청한 정보를 응답해준다.

우리는 그 받은 정보를 쓸 수 있게 파싱해서 사용한다.

_
응답이 툭치면 나오는게 아니라, 요청을 보내면 응답이 올때까지 기다려야 되기 때문에,
일반적인 함수가 아니라 코루틴이나 비동기를 사용한다.

아래의 예시는 내가 post를 사용할 때 썼던 코드들이다.

  StartCoroutine(SendPost(serverUrl, param, (callback) =>
        {
            Debug.Log(callback);
        }
    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
            {
                Debug.LogError("Failed");
                callback("Error");
            }
        }
    }

 


작성일 : 2022년 10월 7일

 

 

 

기존에는 velog에 글을 작성했었다. 

그쪽이 좀 더 개발자 친화적인 분위기라서 좋았지만, 써놓은 글에 대한 분류가 힘들어서 확장이 어렵겠다고 판단했다.

앞으로는 좀 꾸준히 글을 작성해 보겠다는 다짐과 함께 새로 만들었다.

 

velog에 있던 글들은 건질만한 것들을 이쪽에 그대로 옮겨놓을 생각이다.

 

+ Recent posts