강의에서 SkillSystem의 Unregister함수를 보면
Destroy(skill);을 통해 Skill 객체를 지우는데
이때 메모리 누수가 발생하지 않는지 궁금합니다.
예를 들어 Skill은 SetUpStateMachine() 메소드에서
StateMachine.onStateChanged 이벤트에 익명메소드로 구독을 하는데
StateMachine.onStateChanged += (_, newState, prevState, layer)
=> onStateChanged?.Invoke(this, newState, prevState, layer);
구독을 해제하는 부분은 따로 찾지 못해서
이런 경우 메모리 누수가 없이 이벤트도 Skill 객체와 함께 정상적으로 삭제가 되는지 궁금합니다.
아직 메모리 관리에 대한 지식이 부족해 이러한 경우 메모리 누수가 발생하는지 아닌지를 어떻게 찾아봐야 할지 모르겠어서 강사님에게 질문드립니다.
수강해주셔서 감사합니다.
기본적으로 순수 C# 객체들은 참조 Count가 0일 경우 가비지 컬렉터에 의해 메모리 수집이 되므로 메모리 누수가 일어날 일은 없습니다. C#에서 메모리 누수는 유니티처럼 내부적으로 C++ Code를 돌리고 있거나 Data Stream을 다루는 등 특정 상황에서만 일어날 수 있습니다. 이 경우 명시적인 Dispose 함수 사용을 권고하기 때문에 그러한 내용이 없다면 메모리 누수 걱정은 안하셔도 됩니다.
StateMachine을 다른 객체가 들고 있었다면 구독 해제를 해줬어야겠지만 Skill의 StateMachine은 Skill과 Life Time이 같으므로 굳이 구독을 해제해줄 필요가 없습니다.
감사합니다.
답글
최성호
2024.11.12아 제가 다시 이해한 바가 맞는지 여쭤봐도 될까요?
만약 statemachine이 skill과 파괴되는 타이밍이 다르다면 statemachine의 이벤트에 파괴된 skill의 메소드가 참조되어 잇기 때문에 skill이 완벽하게 파괴되지 않지만 원본 코드처럼 statemachine과 sKill이 함께 파괴된다면 딱히 skill의 잔재가 남지 않기 때문에 구독해제를 하지 않아도된다가 맞을까요?
Developer G
2024.11.12맞습니다. 내가 소유하고 있는 객체(=Life Time이 같음)는 굳이 구독 해제를 안해줘도 됩니다. 소멸자를 만들어서 GC.Collect()를 실행해보시면 정상적으로 수집이 되는걸 확인하실 수 있습니다.
statemachine을 skill이 가지고 있기 때문에 statemachine의 이벤트에 skill의 함수를 구독(여기서는 익명메소드로 구독) 하여도 skill이 Destroy될때 문제 없이 삭제되는 건가요?
또 statemachine 이벤트의 skill의 함수를 구독하는 것은 statemachine의 참조 count에 추가되지 않는건가요?
잘 이해가 되지않아 추가질문 드립니다.
답글
Developer G
2024.11.12자세한건 가비지 컬렉션 이론 및 추적 가비지 컬렉션(Tracing Garbage Collection)에 대한 내용을 학습하시면 아실 수 있으십니다.
간략히 설명 드리면, 가비지 컬렉터는 단순 참조 카운팅 뿐만 아니라 특정한 조건으로 선별된 Root Set(메모리 뭉치)에서 메모리 연결 추적을 통해 접근할 수 없는 메모리는 수집 대상으로 판단합니다. Skill과 StateMachine 모두 Root에서 접근할 방법이 없다면 상호 참조와 상관 없이 가비지 수집 대상이 됩니다.
이 때문에 C#에서 상호 참조로 인한 메모리 누수 문제는 제가 알기론 없구요, 앞서 설명드렸듯이 특수한 상황을 제외하곤 메모리 누수 날 일이 잘 없습니다.
답변 감사합니다
답글