목록전체 글 (157)
Coding Memo
UnityWebRequest.Post()를 사용하여 웹 서버에 응답을 요청했을 때, 다음과 같은 에러가 나타날 수도 있다.(나타나지 않을 때도 있어서 이유를 찾는데 오래 걸렸다...) A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details. 에러에 나와있듯이, stack traces를 full로 설정하고 editor log나 player log를 확인을 했지만, 아래 에러 이상의 내용이 전혀 나타나지 않았다.(...)또한, 어떤 컬렉션이 누수를 발생시키고 있는지도 알 수가 없었다.... 이 문제를 해결하면서 살펴본 코드는 다음 포스트에 있다.https:/..
이 글은 해당 에러를 확인하면서, 정리한 글이다. 먼저 내가 사용했던 코드를 다시 한번 살펴보자.public IEnumerator PostCo(string url, T data, Action callback){ string json = Newtonsoft.Json.JsonConvert.SerializeObject(data); using (UnityWebRequest request = UnityWebRequest.Post(url, json)) { byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(json); request.uploadHandler = new UploadHandlerRaw(bodyRaw); req..
Unity에서 UnityWebRequest를 통해, Https 연결을 요청할 때, 다음과 같은 에러가 발생 할 수 있다.Curl error 60: Cert verify failed. Certificate Common Name(CN) does not match with the expected CN. UnityTls error code: 7 이 에러는 말그대로 Https 연결 시, 인증 문제로 나타나는 에러이다.단순히 말해서, SSL 인증서 문제이다. 때때로, 이 에러는 자신의 컴퓨터의 루프백 주소(127.0.0.1)을 이용할 때 나타나기도 한다. 간단히 자신의 컴퓨터로 테스트를 해보고 싶은데 해당 에러가 뜬 다면, 다음 2가지 방법으로 해결 할 수 있다. 1. 루프백 주소(127.0.0.1) 대신, "lo..
3가지 직렬화를 비교해보자. 1. BitConverter를 이용2. Unsafe 코드인 StructureToPtr을 이용하여 메모리 내용을 그대로 이용3. 직접 바이트를 조작속도 비교 C++로 작성된 서버와 C#으로 작성된 클라이언트의 통신에서 패킷 정보 파싱을 위해 PacketHeader라는 구조체를 이용했다. PacketHeader는 unsigned int16 (ushort)의 Id 값과 같은 타입의 Size로 이루어져 있다. C++의 placement new를 이용해서 메모리에 있는 값 그대로 전송하여 C#에서 파싱하는 형태이다. PacketHeader는 다음의 구조이다.[Size, 2 bytes][Id, 2 bytes] C#에서도 위 메모리 순서를 지키면서 다음 구조체를 작성하였다.[StructL..
문제 소켓이 연결이 되었음에도 불구하고, getpeername() 함수가 SOCKET_ERROR를 반환하고, WSAGetLastError() 값이 10057(WSAENOTCONN)이었다. 해당 소켓에 대해 WSASend 및 WSARecv는 정상적으로 작동하였고, getsockname또한 정상적으로 작동하였다. 해결 연결된 소켓에 대해 SO_UPDATE_CONNECT_CONTEXT 옵션을 설정해 주면 된다.이후 getpeername은 정상적으로 작동하고, remote endpoint의 주소와 포트 번호를 가져올 수 있다. 설명 SO_UPDATE_CONNECT_CONTEXT는 소켓이 연결 된 이후에, 소켓의 속성을 업데이트하는 옵션이다. 이 옵션은 ConnectEx, WSAConnectByList, WSA..
윈도우에서 지원하는 concurrent에 대한 자료구조 헤더가 있는데, 이들은 lock-free로 구현되어 있으니 이 쪽을 사용하는 것이 훨씬 더 도움이 될 수도 있겠다 ㅋㅋ std::mutex를 이용한 lock과 std::priority_queue를 사용하여 간단한 concurrent 우선순위 큐를 만들어보았다.기본적인 push 및 pop 외에, 지정된 조건에 따라 결과값을 반환하는 TryPop등의 함수도 포함했다.상황에 따라 필요할 수도 있기 때문이다. (예를 들어, top의 객체를 확인하고 이 객체가 어떤 조건이 맞을 경우에만 pop을 해야할 필요가 있을 때, top과 pop을 따로하면 atomic하게 실행시켜야되는 데, 이 과정에서 외부 lock을 걸어야 되기 때문이다.) 추가적으로, 이동연산자를..
Summaryconst로 선언된 포인터는 포인터 값 뿐만 아니라, 해당 포인터가 가리키는 데이터의 변경도 막는다. 따라서 const 변수와 마찬가지로, const 포인터는 const가 아닌 값으로 캐스팅 할 수 없다. const로 선언된 포인터는 해당 포인터가 가리키는 데이터의 변경을 막는다. 만약, const 포인터가 가리키는 값을 변경할 필요가 있는 경우, `const_cast`를 사용하여 const 속성을 없애주면 된다.다음은 예시 코드이다.using uint = unsigned int;using ubyte = unsigned char;uint t = 0xffffffff;std::cout someInt(4, 0xFF); // it represents max of unsigned int { uby..
ReadWriteLock의 특징은 다음과 같다.1. Spinlock으로 구현2. unsigned int 값의 flag를 하나 지정하여, 상위 2바이트는 write중인 thread_id, 하위 2바이트는 현재 read중인 스레드의 수를 나타냄3. thread_id는 thread가 새로 시작할 때 id 부여4. write 중일 때는 다른 스레드들이 이 lock을 얻지 못함5. wrtie 중이 아닐 때는 다수의 스레드가 동시에 read 가능6. EMPTY_FLAG (어느 스레드도 lock을 가지고 있지 않을 경우)는 0x00000000 서버-클라이언트의 연결에서 가끔씩 패킷을 전송 할 때, 세션의 전송 함수 내의 WRITE_LOCK에서 spin-timeout이 나타났다. 즉, deadlock이다. 이번 문제의..