2007. 7. 21. 23:58

프로그래밍팁: malloc과 free 시점

여러 사람이 윈도우 프로그래밍(VC++)을 하다 보면 다양한 형태의 라이브러리가 자신의 코드에 포함되고 여러 API를 사용하기 마련이다. 이 때 API에 파라미터로 넘어가는 포인터에 메모리를 할당하는 주체는 포인터를 사용하는 API 호출함수가 될 것이다. 쓰는 쪽에서 할당(malloc)하고 다 쓴 후 해제(free)하는 것이 기본적인 접근 방법일 것이다.

사용자 삽입 이미지
그러나 세상사 그리 뜻대로 되는 일이 얼마나 있겠는가? 코딩을 하다보면 여러 요인으로 라이브러리 내에서 메모리를 동적으로 할당하고 API 호출 함수쪽에서 이를 해제해야 하는 일이 발생하고 만다. 이러한 코딩 방식은 메모리릭(memory leak)을 유발하는 가장 적!극!적인! 코딩방식으로 다니는 회사가 마음에 안들때는 가끔씩 사용해 주는 것이 좋다. 아무리 주석으로 이 API를 쓰면 free를 꼭 해달라라고 써 놔도 시간이 지나고 여러사람이 사용하다 보면 결국 누수가 발생하고 만다. (쓰기만 하면 메모리 릭이 나서 모두들 꺼려하지만 상당량의 코딩을 다시하는 것은 귀찮고 누구하나 신경쓰지 않기 때문에 궁시렁 거리면서 계속 쓰게 되는 API 라이브러리가 탄생하는 것이다..ㅎㅎㅎ)

그런데 이러한 팁(응?)을 사용하다 보면 가끔 API 라이브러리 안에서 할당한 메모리가 API 호출 함수에서 해제되지 않는 불상사가 생기고 만다. 프로그램은 쀍~ 하고 죽어버리기 때문에 이건 좋지 않다. 이런 경우 API 라이브러리를 만든 사람과 API 호출 함수를 만든 사람들은 서로 잘 못 한 것이 없기 때문에 상대방의 정신상태를 과격하게 지적하는 상당량의 말들을 쏟아내고 프로젝트는 점점더 지옥 속으로 빠져드는 것이다.

이러한 상황을 극복하기 위해서 다음과 같은 코딩 패턴을 추천한다.(어찌보면 당연하지만)

//Hell.DLL (API Lib)
//pDeveloper에 스트레스 길이만큼 malloc()해서 적당히 태운다음 반환하는 함수
  //void vBurn(char *pDeveloper);
//pDeveloper를 해제(free)하는 함수
  //void vFree(char *pDeveloper);

//Company 프로그램(API 호출 함수)
void main()
{
  HANDLE hHell = LoadLibrary("Hell.dll");
  char *pJInyoung = NULL;
  while(1)
  {
      hHell->vBurn(pJInyoung);

      hHell->vFree(pJInyoung); //여기서 free(pJInyoung); 하면 될 수도 안될 수도 있다.
  }
}

free(pJInyoung);이 될 수 도 안될 수도 있다는게 지옥이다. 보통 안될 때는 hHell.DLL 내에서 malloc한 주소 값과 Company프로그램에서 pJInyoung의 주소가 같기 때문에 나같은 초급 개발자는 당췌 free가 안되는 이유를 알 수가 없다. 또 Debug 모드에서는 안되면서 Release 컴파일 모드로는 되버리는 경우가 있기 때문에 마음속에 '불안감'이 동골동골 굴러다니게 되는 코드가 되는 것이다.

main과 DLL은 서로 같은 메모리 스페이스를 사용하기 때문에 DLL과 exe 프로그램의 주소체계는 같다고 보면 된다. 서로 다른 메모리 스페이스를 사용한다면 vBurn에 포인터를 넘겨서 Hell.dll 안에서 작업하는 것 자체가 불가능할 것이다. 즉 주소가 잘못되서 이런 문제가 발생하지는 않는다.

실제 문제는 라이브러리와 프로그램에서 VC++이 사용하는 Heap이 서로 다르기 때문에 발생한다. VC++에서는 debug heap, crt heap, mp heap 등 다양한 Heap이 존재한다. 각 Heap들은 allocation/deallocation 방식도 다르고 자기가 사용하는 메모리 영역도 다르기 때문에 한쪽 힙에서 할당한 메모리를 다른쪽 힙에서 해제하려고 하면 메모리 릭이 발생하거나 혹은 에러를 내는 것이다. 따라서 dll에서 사용한 힙과 exe에서 사용한 힙이 같을 경우에는 전혀 문제가 발생하지 않게 되는 경우도 있다. 우연히 릴리즈모드에서 사용 heap이 같아서 free(pJinyoung)이 되는 경우가 있을 수 있는것이다.

진짜 문제는 나같은 초급 개발자는 일반적으로는 dll에서 어떤 힙을 사용했는지 모르게 되는 경우가 대부분이라 더욱 난감하다. 따라서 DLL에서 메모리를 할당했으면 DLL 안에서 free를 해주는 것이 세상을 아름답게 하는 코딩방법이라고 주장해 본다. ㅎㅎㅎ

사용자 삽입 이미지

'이야기' 카테고리의 다른 글

프로그래밍팁: 다이얼로그 디자인 복사하기  (2) 2007.08.20
IT 개발자의 푸념들  (0) 2007.07.11
하드보일드 드리머  (0) 2006.12.15