묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
락프리의 실무에서 사용 질문
락프리 구조를 사용하지않는다고 하셨는데 락프리를 써야 서버의 성능이 제대로 나오는것 아닌가요? 오히려 너무 어려워서 제대로 만든것이 아니라면 서버가 죽거나 오류가 날수 있기때문에 안쓰는 건가요?락을 사용해서 데이터 하나에 접근을하면 싱글 스레드보다 성능이 낮을것같아서 질문드려요멀티스레드를 사용하는 경우가 실무에선 많이 없을까요? 아니면 boost.asio에 있는 lockfree자료구조를 사용하나요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
에러코드
Spawn 수업을 진행 하던 도중에 , 클라이언트 빌드 이후에 발생한 에러인데 어느부분에서 발생하는지 몰라서 에러코드를 남겨봅니다.. 자동화 이후 빌드까진 다되었었는데 발생했습니다. 캐시파일들같은 파일들을 다 삭제하고 리빌드를 해도 동일한 오류가 발생합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
32bit threadID와 16비트 상위 WriteFlag에 대해
32비트짜리 threadID를 비트 연산으로 16비트 옮겨준뒤 짤라준 것을 WriteFlag에 담는 과정에서 손실이 일어나는거 아닌가요? 그래서 현재 ThreadID와 _lockFlag의 WriteFlag를 다시 16비트 옮겨준 값이랑 비교했을 때 일치하지 않는 문제가 발생할 수 있지 않나요? 강의 18:40초입니다. ( ThreadID를 16비트로 관리하지 않는 이유는 또 무엇인가요??? )
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
언리얼 버전
안녕하세요 항상 수준높은 강의해주셔서 감사합니다강의에선 5.3언리얼 버전으로 진행하는데, 최신버전인 5.6 버전으로 진행해도 무방할까요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
mutex와 sleep 차이점
mutex도 커널로 sleep가 되는걸로 알고 있는데 스핀락을 구현하면서 sleep를 같이 구현하는것과 mutex를 사용하는것의 차이가 궁금합니다
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
ProtoBuf UE 연동 문제
Spawn #2 따라하고 실행해보는데 메모리 충돌로 인해 언리얼 크래쉬가 발생하네요혼자 열심히 시도해 본 결과 UE FMemeory와 ProtoBuf 소멸자에서 delete 되는 부분에서 UE delete 오버라이드 문제인 것 까진 알게 되었으나 어떻게 해결해야 할 지 모르겠어서 질문 드립니다UE 5.6 버전이고, ProtoBuf는 C++ 5.29.5(29.5) 버전입니다vcpkg를 사용해서 라이브러리 다운 받았고 /MD 동적 라이브러리로 UE 프로젝트에 포함시켰습니다 (dll로 인해서 new/delete 오버라이드로 인한 메모리 충돌 문제가 더 쉽게 발생하여 /MT로 포함하는 것이 나을 수도 있겠다고 LLM(gpt, grok) 등이 말한 내용을 적용하고자 하였으나 빌드를 실패하여 그 부분은 진행하지 못하였습니다)다음 이미지는 실행했을 때 크래쉬가 발생하는 부분과 로그 일부 입니다LoginId:468bde9140a0ef5bd78746b7d5b86a2cEpicAccountId:e6607fa7037e41448797c486f54e5315Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x0000023d9d00116fUnrealEditor_CoreUnrealEditor_CoreUnrealEditor_S1!operator delete() [C:\Program Files\Epic Games\UE_5.6\Engine\Source\Runtime\Core\Public\HAL\PerModuleInline.inl:9]UnrealEditor_S1!Protocol::PlayerInfo::`scalar deleting destructor'()libprotobuf!google::protobuf::internal::RepeatedPtrFieldBase::DestroyProtos() [C:\Users\yudle\vcpkg\buildtrees\protobuf\src\v5.29.5-5bafd96eab.clean\src\google\protobuf\repeated_ptr_field.cc:90]UnrealEditor_S1!Protocol::S_LOGIN::~S_LOGIN() [D:\GitHub\S1\Source\S1\Network\Protocol.pb.cc:586]UnrealEditor_S1!std::_Func_impl_no_allocServerPacketHandler::Init'::2'::<lambda_1>,bool,TSharedPtr<PacketSession,1> &,unsigned char *,int>::_Do_call() [C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\INCLUDE\functional:810]UnrealEditor_S1!PacketSession::HandleRecvPackets() [D:\GitHub\S1\Source\S1\Network\PacketSession.cpp:37]UnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_CoreUnrealEditor_CoreUnrealEditor_CoreUnrealEditor_CoreUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_UnrealEdUnrealEditor_UnrealEdUnrealEditorUnrealEditorUnrealEditorUnrealEditorUnrealEditorUnrealEditorkernel32ntdllS_LOGIN 패킷의 소멸자에서 오염된 메모리 접근 문제로 크래시가 발생한 것으로 보입니다
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
실무에서는 어떠한 코드 스타일을 사용하는지 궁금합니다
물론 회사마다 다르고 각 회사의 기존 스타일을 따라야 하는게 맞지만 독학하는 입장에서는 clang-format이 제공해주는 힌트들, 구글 스타일 가이드 혹은 인터넷에서 나오는 여러 c++ 스타일 가이드를 보면서 어떠한 스타일을 채택해 사용할지 고민이 됩니다미리 손에 익혀두며 학습하고 싶어 질문드려 봅니다
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Stomp Allocator의 Release함수에 대한 질문입니다.
예들 들어서, 할당된 메모리 주소가 0x1000~0x3000이고, 실제 사용하려는 메모리 위치를 0x2008로 반환받았다고 가정할 때,const int64 address = reinterpret_cast<int64>(ptr);const int64 baseAddress = address - (address % PAGE_SIZE);이 계산으로 전체 메모리 해제가 가능한가요? 메모리 해제 부분이 이해가 잘 안되네요..
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
공부법 관련해서
루키스님 강의 잘 듣고 있습니다. 서버 강의 재밌게 듣고 있는데 제가 공부 하는 방법이 시간이 많이 드는데 시간을 많이 쓰는 거에 비해 학습에 크게 도움이 되는 것 같지 않아서 질문 드립니다.저는 강의를 듣고 복습 차원에서 노트에 그날 들었던 강의들의 내용을 정리하고 코드에 대해 이해해보려고 검색 하면서 공부하고 있는데 노트에 필기 하는데도 시간이 많이 들고 필기에 투자 하는 시간 대비 외우는 게 잘 안되는 거 같아서 이 방식이 잘못되었다고 느껴지네요...루키스님은 어떤 식으로 공부 했는지 궁금합니다!! 진로는 서버 쪽으로 밀고 가려고 하고 있습니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
MakeShared 함수 관련
52강 ServerService 수강 중 13:54 때에 MakeShared함수를 이용해서 shared_ptr을 생성해주는 부분이 있는데, 똑같이 따라하던 중 제 프로젝트에서 컴파일 에러가 발생했습니다.첨부해주신 프로젝트와 비교해보니 MakeShared함수가 변경되어 있더라구요기존에 Memory 관련 강의 이후에는 변경된점이 없어서 어느 시점에 변경된건지 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
지금까지 서버코어에서 만든 내용에 대해 궁금한 점이 있어서 질문 드립니다.
지금까지 개발한 서버코어는 IOCP기반의 비동기 논블로킹 방식이라 생각됨니다.Send에서는 SendBuffer를 sendEvent에 등록한 다음 Scatter-Gather로 모아서 ::WSASend로 송신을 수행하는 것으로 이해했습니다.Recv에서는 ::WSARecv에서 수신을 받기 전에 버퍼에 패킷 데이터를 조립한 다음에 바로 함수를 실행하고 있습니다.이벤트 데이터는 사실상 비어있고 callback함수도 없으니 ::WSARecv는 수신완료를 CP에 보내는 것 밖에 없다고 봅니다.제가 볼때 수신부는 제가 이해한 비동기 방식과는 다르게 돌아가는 것 같습니다.어떻게 이해해야 할까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
운영체제관련 질문입니다
운영체제도 같이 공부를 하고싶어 소위 공룡책이라는 운영체제책을 사서 공부를 하고있습니다 운영체제를 처음부터 만들어보는 실습 책들을 따라해보면 이라고 하셨는데 어떤책을 추천해주시는지 알수있을까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
send하려는 데이터 크기가 크면 memcpy에서 문제가 발생할 것 같습니다.
여기서 만약 복사 시작지점 + len 이 array 범위 밖이면 sendBuffer->Close(len) 안에서ASSERT_CRASH(_allocSize >= len); 으로 체크하기 전에 array 정적배열에 memcpy를 하니까 이 부분에서 문제가 생길 것 같습니다.OnRecv로 들어온 buffer가 6001바이트짜리 라면 Open(4096)이 성공하고, 6000크기의 배열에 6001크기를 memcpy 하니 오버플로우가 일어날 것 같습니다.아니면 Open(4096)으로 chunk로부터 사용할 수 있는 공간을 할당 받을 때 len이 4096보다 반드시 작을거라는 확신이 있기 때문에 memcpy 전에 확인하지 않는건가요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
Snapshot base vs packet oriented
Hello Master 🙂I would like to ask wich method is prefered in wich case. Most mmo code i seen either go packet way like in this course or Client send commands wich contains input + mouse postion + fields that allow you to for example specify operation type like interact, consume etc. Server respond each tick with snapshot of zone you are around your aoi with all possible data with delta comporession so you get only new information. Wich approach is prefered, on wich it depends? Does they have some serious perfomance gains when you stick to one of them? Or its just matter of architecture your team prefer?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
Is there official app or something that allow you watch lectures offline?
Is there official app or something that allow you watch lectures offline?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
What is more capable of m2 c# server or cpp from episode 4?
Hello, 1 . What is more capable of m2 c# server or cpp from episode 4? Would it make sense to use cpp version of server with c# unity client?Is it better to keep c# integration inside unity engine or create bindings to cpp client and only call bindings from c# unity?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
메모리 풀 질문있습니다.
우선 좋은강의 만들어주셔서 감사합니다.제가 질문드릴건 메모리풀을 1024까지는 32바이트단위로 만드는데, 그러면 32바이트전용 풀 64바이트 전용 풀 이렇게 만들어질거고근데 이제 요청하는데 16바이트 요청을 1000번하면,32바이트 풀안에 메모리헤더 큐가 1000개가 생기는거죠?? 해제안했다는 가정하에
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
메모리 풀 질문있습니다.
우선 좋은강의 만들어주셔서 감사합니다.제가 질문드릴건 메모리풀을 1024까지는 32바이트단위로 만드는데, 그러면 32바이트전용 풀 64바이트 전용 풀 이렇게 만들어질거고근데 이제 요청하는데 16바이트 요청을 1000번하면,32바이트 풀안에 메모리헤더 큐가 1000개가 생기는거죠?? 해제안했다는 가정하에
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
JobQueue의 Push Execute쪽 코드 질문
해결 ++아래 질문 내용을 글로벌 큐에서 추가로 처리해 주는 거였습니다.삭제가 안되서 최상단에 남깁니다.이것저것 건들면서 연습하다 보니 제 환경에서 글로벌 큐 호출을 안해서 문제였습니다. 안녕하세요?루키스님 강의를 참고하여 더미 프로젝트 하는 중에 문제가 식별 되어제가 분석한게 맞다면 강의 코드에 문제가 있어 제보 드려봅니다.문제라고 생각되는 부분은 JobQueue 클래스인데요, 문제 상황은부하가 있는 상황에서 '워커스레드를 2개 이상 돌릴 때, Execute()함수가 실행되지 않는'점을 확인하였습니다.jobCount 관련 변수의 조건이 어디서 안 맞는 것 같아서 생각해보건데,아래와 같은 경우라고 생각됩니다.// JobQueue.cpp void JobQueue::Execute() { ... if (_jobCount.fetch_sub(jobCount) == jobCount) { // 여기서 다른 워커 스레드의 _jobCount.fetch_add 발생?! LCurrentJobQueue = nullptr; return; } ... } } 그렇기 때문의 이후의 잡들이 처리되지 못하고 해당 부분에서 prevCount가 계속 쌓이고 있었습니다.// JobQueue.cpp void JobQueue::Push(JobRef job, bool pushOnly) { const int32 prevCount = _jobCount.fetch_add(1); _jobs.Push(job); // WRITE_LOCK // 여기서 prevCount가 계속 쌓여 0이 아님 if (prevCount == 0) { //그러므로 이 부분의 Excute()도 실행되지 않음 ... } 아래는 해당 클래스 cpp 전문입니다.귀한 시간 내시어 확인해주시면 감사하겠습니다!#include "pch.h" #include "JobQueue.h" #include "GlobalQueue.h" /*-------------- JobQueue ---------------*/ void JobQueue::Push(JobRef job, bool pushOnly) { const int32 prevCount = _jobCount.fetch_add(1); _jobs.Push(job); // WRITE_LOCK // 첫번째 Job을 넣은 쓰레드가 실행까지 담당 if (prevCount == 0) { // 이미 실행중인 JobQueue가 없으면 실행 if (LCurrentJobQueue == nullptr && pushOnly == false) { Execute(); } else { // 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다 GGlobalQueue->Push(shared_from_this()); } } } // 1) 일감이 너~무 몰리면? void JobQueue::Execute() { LCurrentJobQueue = this; while (true) { vector<JobRef> jobs; _jobs.PopAll(OUT jobs); const int32 jobCount = static_cast<int32>(jobs.size()); for (int32 i = 0; i < jobCount; i++) jobs[i]->Execute(); // 남은 일감이 0개라면 종료 if (_jobCount.fetch_sub(jobCount) == jobCount) { LCurrentJobQueue = nullptr; return; } const uint64 now = ::GetTickCount64(); if (now >= LEndTickCount) { LCurrentJobQueue = nullptr; // 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다 GGlobalQueue->Push(shared_from_this()); break; } } }
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
JobQueue의 Push Execute쪽 코드에 문제가 있는 것 같아 말씀 드려봅니다
안녕하세요? 루키스님 강의를 참고하여 더미 프로젝트 하는 중에 문제가 식별 되어제가 분석한게 맞다면 강의 코드에 문제가 있어 제보 드려봅니다.문제라고 생각되는 부분은 JobQueue 클래스인데요, 문제 상황은'워커스레드를 2개 이상 돌릴 때, Execute()함수가 실행되지 않는'점을 확인하였습니다.jobCount 관련 변수의 조건이 어디서 안 맞는 것 같아서 생각해보건데,아래와 같은 경우라고 생각됩니다.// JobQueue.cpp void JobQueue::Execute() { ... if (_jobCount.fetch_sub(jobCount) == jobCount) { // 여기서 다른 워커 스레드의 _jobCount.fetch_add 발생?! LCurrentJobQueue = nullptr; return; } ... } } 그렇기 때문의 이후의 잡들이 처리되지 못하고 해당 부분에서 prevCount가 계속 쌓이고 있었습니다.// JobQueue.cpp void JobQueue::Push(JobRef job, bool pushOnly) { const int32 prevCount = _jobCount.fetch_add(1); _jobs.Push(job); // WRITE_LOCK // 여기서 prevCount가 계속 쌓여 0이 아님 if (prevCount == 0) { //그러므로 이 부분의 Excute()도 실행되지 않음 ... } 아래는 해당 클래스 cpp 전문입니다.귀한 시간 내시어 확인해주시면 감사하겠습니다!#include "pch.h" #include "JobQueue.h" #include "GlobalQueue.h" /*-------------- JobQueue ---------------*/ void JobQueue::Push(JobRef job, bool pushOnly) { const int32 prevCount = _jobCount.fetch_add(1); _jobs.Push(job); // WRITE_LOCK // 첫번째 Job을 넣은 쓰레드가 실행까지 담당 if (prevCount == 0) { // 이미 실행중인 JobQueue가 없으면 실행 if (LCurrentJobQueue == nullptr && pushOnly == false) { Execute(); } else { // 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다 GGlobalQueue->Push(shared_from_this()); } } } // 1) 일감이 너~무 몰리면? void JobQueue::Execute() { LCurrentJobQueue = this; while (true) { vector<JobRef> jobs; _jobs.PopAll(OUT jobs); const int32 jobCount = static_cast<int32>(jobs.size()); for (int32 i = 0; i < jobCount; i++) jobs[i]->Execute(); // 남은 일감이 0개라면 종료 if (_jobCount.fetch_sub(jobCount) == jobCount) { LCurrentJobQueue = nullptr; return; } const uint64 now = ::GetTickCount64(); if (now >= LEndTickCount) { LCurrentJobQueue = nullptr; // 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다 GGlobalQueue->Push(shared_from_this()); break; } } }