오늘 아라(KAIST의 대표적인 텔넷 서비스, ara.kaist.ac.kr)에서 누군가 이런 질문을 했다.
new가 있으면 delete를 반드시 해줘야 하나요?
open source 여러 개를 받아보았는데, new의 개수만큼 delete가 없는 경우가 있더라고요. 그래서 일일이 delete를 수행해 주고 있는데, 제가 괜히 new로 잡히지 않은 부분을 delete해서 프로그램이 오작동을 일으키는 것은 아닌지 걱정됩니다. 그렇다고 delete를 안해주자니 그것도 두렵구요.
어느 정도 명성 있는 프로그램에서도 new와 delete의 개수가 같지 않아 조금은 혼란스럽습니다.
아, 그리고 혹시 프로그램 실행 도중에 예기치 못한 곳에서 프로그램이 종료되면 delete를 수행해 주지 못할텐데, 그러면 어떤 일이 벌어지나요?
초보 프로그래머 올림… ^^
아직 아무도 답변을 안 달았기에 내가 한마디 했다. 답변을 달면서 줄곧 좀더 잘 설명해주면 좋을텐데라고 생각했다. 다행스럽게도 내 블로그에는 나의 허접한 답변을 글로 남길 필요가 없다. 겐도형이 뒤이어 자신의 내공을 보여주는 답변을 작성해 주었기 때문이다. 아마도 겐도형이 본인의 블로그에 이 글을 남길 것 같지는 않다. 그래서 염치불구하고 그 답변을 여기에 옮겨놓는다.
메모리 관리를 제대로 하지 못하면 Dangling Object가 생겨서(new를 하고 delete를 하지 않음) 메모리 사용량이 지속적으로 증가하여 장시간 구동시 메모리 리소스를 고갈 시킬 수도 있고 로직상의 오류로 이미 지워진 객체에 대해 Dangling Pointer(이미 지워진 객체를 가르키는 포인터)가 생겨 Access Violation이나 오동작을 유발 할 수도 있습니다.
C나 C++에서 메모리 관리는 동적 힙 메모리를 사용하는 상황에서는 매우 중요한 프로그래머의 능력이기도 합니다.
new와 delete의 개수에 대해서 일반적으로는 동일해야 합니다만 반드시 그런것은 아닙니다. 객체간의 관계에 따라 생성해서 다른 객체에 넣어주면 알아서 지워주는 경우도 있습니다. 반대로 new로 객체를 생성하는 것이 아닌 다른 로직(클래스나 함수)을 통해 객체를 생성받을 수도 있죠. 생성자와 파괴자가 항상 Public이어야 한다는 제약 조건이 없답니다. (가령 생성자가 Protected로 선언되면 그냥 new로는 객체 생성이 불가능 합니다.)
최근 .NET Framework의 CRL을 사용하다 보면 객체를 new는 하는데 그대로 방치해 버리기도 합니다. 오랫동안 C/C++에서 포인터 사용에 각별히 신경을 쓰던 저로서는 참을 수 없는 상황이긴 합니다만 Visual C++에서 CRL을 사용하는 경우 Garbage Collecting이 지원되어 일부 상황에서는 delete를 하지 않게 되었습니다. 동작중에 객체에 대한 참조가 사라지면 알아서 지워집니다. 비슷한 것이 Visual C++ 2005에서는 gcnew라는 놈이 생겨서 객체를 Garbage Col.을 지원하는 힙에다 생성할 수 있게 되었습니다. 이런 부분은 참고로 알아 두시기 바랍니다.
메모리의 생성과 파괴는 반드시 Pair가 되어야 합니다만 그것이 순수한 코드 그 자체가 아니라 로직적으로 매칭이 되어야 합니다. 정확히 delete 구문이 보이지는 않겠지만 어디선가 누군가에 의해 생성된 객체는 안전하게 지워져야 합니다.
마지막으로 프로그램 종료시에 미반환된 메모리 리소스는 일반적으론 프로세스 영역이 사라지면서 일괄 반환되게 되어 있습니다. 하지만 모든 프로그램이 그렇듯 운영체제도 버그가 있어서 100% 반환된다고 보장은 하지 못합니다. 윈 9X시절에는 50% 정도 되고 그 이후의 운영체제들은 한 90%? 최근의 운영체제들은 99.9999% 정도 된다고 볼 수 있겠지만 반대로 100%는 아닙니다.