네이티브 코드 체계에선 메모리(일반적인 메모리 , COM객체,Windows HANDLE 등등) 누수 탐지 기능이 반드시 필요하다. 컴파일 타임에서 논리적으로 아무리 완벽한 체계를 제공한다고 해도 말이다.
최근 MS는 COM을 사용하는 예제에서 CComPtr 사용을 적극 권장하고 있다. C++/CX에선 명시적으로 CComPtr을 사용할 필요없이 ^객체가 스마트포인터를 내장하고 있고 UWP프로젝트가 아닌 경우, 예를 들어 DX12샘플같은 경우 CComPtr을 사용하고 있다.
CComPtr뿐 아니라 컴파일러 레벨에서 스마트포인터를 제공하는 C++/CX에서조차 리소스 누수 탐지 기능(CRTHeap의 leak체크와 같은)은 반드시 필요하다.
물론 MS나 되는 기업에서 만든 스마트 포인터의 논리와 코드 품질을 의심하는 것은 아니다. lambda캡쳐로 전달하든, 함수 파라미터로 전달하든, STL과 섞어 사용하든 CComPtr과 ^객체의 레퍼런스 카운트는 언제나 정확히 맞아떨어질것이다.
단 의도하지 않게 메모리를 손상시키는 경우는 제외하고.
아무리 논리가 완벽해도 같은 프로세스 안에서 메모리를 자유롭게 억세스하는것이 가능하기 때문에 메모리 범위를 넘어가는 등의 사소한(사소하지만 무서운) 실수로 CComPtr의 정합성이 깨질수 있다. 이런 경우 프로세스를 종료하는 시점에서 누수체크나 heap corruption 체크 기능이 반드시 필요하다.
물론 프로그래머의 실수지만 그 실수의 원인을 알아내려면 눈으로 코드를 살펴보는 수준으로는 한계가 있다.
그런데 애플에서 나쁜것만 배워가지고…
UWP같은 경우 명시적 종료가 불가능하기 때문에 정확한 누수 탐지가 불가능하다. 임의의 순간에 heap의 스냅샷을 찍어서 스냅샷을 비교하는 정도는 가능하지만 이것은 기존 win32환경에서 명시적 종료 타이밍에 체크할 수 있는 것들에 비해 상당히 한계를 가진다.
적어도 디버그 모드에선 명시적 종료가 가능해야하고 명시적 종료 타이밍에 핸들,COM객체,heap메모리 등 자원이 완벽하게 해제되었는지 확인할 수 있어야한다.
CComPtr을 쓰면 너희들이 직접 AddRef(), Release()호출하지 않아도 되고 그럼 leak이 발생하지 않을꺼야…라고 주장하는 느낌인데 전혀 그렇지 않다는 말을 하고 싶다.
AddRef(),Release()를 수동호출해서, 그래서 실수해서 ref count를 못맞춘다 해도 사실 상관없다. win32에서라면 DX debug런타임이 종료타이밍에 리소스가 새는걸 알려준다. Release()는 현재 ref count를 반환한다. COM의 AddRef()와 Release()는 iOS의 OBJ-C보단 훨씬 낫다. Application Verifier로 핸들이 새는지 힙을 깨먹었는도 체크할 수 있다. 명시적인 정상종료만 가능하다면 말이지.
MS만의 얘기가 아니다. 플랫폼 제공업체들도 그렇고 어플리케이션 개발사도 그렇고 프로그래머들도 그렇고 코딩 환경이 버그를 좌지우지 한다고 믿는게 나로선 너무 바보같아 보인다.
중요한건 테스트하고 디버깅할 수 있는 환경이지 버그를 원천적으로 봉쇄한다고 ‘믿는’ 코딩 환경이 아니다.