inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버

세션 레퍼런스 카운트 관련 질문입니다.

103

블티

작성한 질문수 12

0

 

void Session::ProcessConnect()
{
	_connectEvent.owner = nullptr; // (1)

	_connected.store(true);        // (2)

	// 세션 등록
	GetService()->AddSession(GetSessionRef());

	// 컨텐츠 코드에서 재정의
	OnConnected();

	// 수신 등록
	RegisterRecv();
}

5장 Session#3 강의를 듣고 따라해보다가 클라이언트 프로그램이 위 함수를 실행하다가 터지는 문제가 발생했습니다.

 

디버깅을 해보니

(1)에서 _connectEvent.owner의 strong ref가 1에서 0으로 줄어들면서 세션(this)이 삭제되고

(2)에서 this를 참조하면서 문제가 생긴 것이었습니다.

 

bool IocpCore::Dispatch(uint32 timeoutMs)
{
	DWORD numOfBytes = 0;
	ULONG_PTR key = 0;	
	IocpEvent* iocpEvent = nullptr;

	if (::GetQueuedCompletionStatus(_iocpHandle, OUT &numOfBytes, OUT &key, OUT reinterpret_cast<LPOVERLAPPED*>(&iocpEvent), timeoutMs))
	{
                // (A): 강사님 코드
                // strong ref: 1
		IocpObjectRef iocpObject = iocpEvent->owner;
                // strong ref: 2
		iocpObject->Dispatch(iocpEvent, numOfBytes);
                
                // (B): 제 코드
                // strong ref: 1
                //iocpEvent->owner->Dispatch(iocpEvent, numOfBytes);
	}
	else
	{
		int32 errCode = ::WSAGetLastError();
		switch (errCode)
		{
		case WAIT_TIMEOUT:
			return false;
		default:
			// TODO : 로그 찍기
			IocpObjectRef iocpObject = iocpEvent->owner;
			iocpObject->Dispatch(iocpEvent, numOfBytes);
			break;
		}
	}

	return true;
}

강사님 코드와 제 코드에서 어떤 부분이 다른지 확인해 본 결과 위와 같은 차이가 있었습니다.

 

강사님은 지역 변수로 스마트 포인터를 하나 만들어서 레퍼런스 카운트가 2인 상태로 세션->Dispatch 함수를 호출하는 반면, 저는 레퍼런스 카운트가 1인 상태로 세션->Dispatch 함수를 호출하는 차이가 있었습니다.

 



[질문 1] 혹시 강사님은 코드를 짜실 때 (B)와 같이 코드를 짜면 문제가 생긴다는 걸 인지하고 (A)와 같이 짜신 걸까요? 레퍼런스 카운트를 어느 정도까지 고려하면서 프로그래밍을 하는 것이 좋은지 궁금합니다.

 

[질문 2] 아래와 같이 코드를 수정해서 문제를 해결해도 별 문제가 없을까요?

// 원본 코드
void Session::ProcessConnect()
{
        // RELEASE_REF
	_connectEvent.owner = nullptr; 

	_connected.store(true);

	// 세션 등록
	GetService()->AddSession(GetSessionRef());

	// 컨텐츠 코드에서 재정의
	OnConnected();

	// 수신 등록
	RegisterRecv();
}
// 수정된 코드
void Session::ProcessConnect()
{
	_connected.store(true);

	// 세션 등록
	GetService()->AddSession(GetSessionRef());

        // RELEASE_REF
        _connectEvent.owner = nullptr;

	// 컨텐츠 코드에서 재정의
	OnConnected();

	// 수신 등록
	RegisterRecv();
}

네트워크 MMORPG windows-server

답변 2

1

Rookiss

네 그런 이유가 맡긴 하나 처음 작업할 때 미래를 완전히 예측해서 작업하는 것은 아니고,
문제가 생기면 수정을 하면 되는 것입니다. 지금 하신것처럼요.
그리고 [이렇게 해도 될까요] 시리즈의 질문은 정말 필요한 질문이 아닙니다.
일단 해보시고 정상 작동 여부를 관찰해보세요.
언젠가 문제가 일어난다면 그 또한 좋은 경험치가 될 것입니다.

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다. 블티님, 세션 레퍼런스 카운트 관련하여 질문을 주셨군요. 레퍼런스 카운트는 특히 멀티스레드 환경에서는 매우 중요한 개념입니다. 이를 잘못 관리하면 프로그램이 예상치 못한 시점에 객체를 파괴하여 에러를 발생시킬 수 있습니다.

[질문 1에 대한 답변]
강사님이 코드에서 레퍼런스 카운트를 고려하여 지역 변수 IocpObjectRef로 소유권을 강하게 잡고 있는 이유는 객체가 Dispatch 함수 동안 안전하게 참조될 수 있도록 하기 위함입니다. 레퍼런스 카운트를 늘리면 해당 객체가 더 이상 사용되지 않을 때까지 파괴되지 않음을 보장할 수 있습니다. (B)와 같은 방법으로 코드를 작성할 때, 해당 참조가 유효해야 하는 동안 레퍼런스 카운트가 1로 유지되면 외부의 다른 동작으로 인해 객체가 파괴될 위험이 있습니다.

[질문 2에 대한 답변]
수정된 코드에서 _connectEvent.owner = nullptr;GetService()->AddSession(GetSessionRef()); 이후에 호출하는 방식으로 변경하였기 때문에, 코드의 문제는 해결될 것으로 보입니다. 이는 세션이 실제로 사용되고 난 후에 참조를 해제하도록 하여 객체의 안전성을 높이는 작업입니다. 이런 방식으로 레퍼런스 카운트를 정확히 관리하는 것이 좋습니다. 그러나, 이 역시 컴파일러의 최적화나 환경에 따라 다를 수 있으니 테스트를 충분히 거치는 것을 추천드립니다.

추가적인 관련 내용을 제공하는 게시물은 없지만, 아래 관련 정보를 확인해 보시면 도움이 될 수 있습니다.
- session의 생명주기 관련 질문입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Memory Pool에서 오버플로우 질문입니다.

0

63

2

포토폴리오 및 진로 관련하여 고민입니다.

0

112

1

포토폴리오 관련 고민입니다.

0

62

1

실무에서도 alloc, 스마트포인터 등을 구현해서 쓰는지 궁금합니다.

0

82

2

성능 테스트 결과

0

103

2

게임 서버 Stateful, Stateless 진로 고민

0

121

1

WaitOnAddress와 Sleep의 차이 질문

0

83

1

궁금한거 있습니다.

0

82

2

JobTimer 구동 스레드

0

107

2

TryPop() 동작 관련 질문

0

81

1

로드맵 C#서버 C++서버 방향성 질문

0

148

2

스레드 id를 출력할떄 메인스레드 id도 출력되나요?

0

73

1

생명주기를 위한 의도적 복사

0

86

2

락프리의 실무에서 사용 질문

0

139

2

32bit threadID와 16비트 상위 WriteFlag에 대해

0

101

2

mutex와 sleep 차이점

0

117

1

실무에서는 어떠한 코드 스타일을 사용하는지 궁금합니다

0

152

2

Stomp Allocator의 Release함수에 대한 질문입니다.

0

96

1

공부법 관련해서

0

183

2

MakeShared 함수 관련

0

114

1

지금까지 서버코어에서 만든 내용에 대해 궁금한 점이 있어서 질문 드립니다.

0

144

2

운영체제관련 질문입니다

0

131

1

send하려는 데이터 크기가 크면 memcpy에서 문제가 발생할 것 같습니다.

0

117

2

메모리 풀 질문있습니다.

0

124

1