C++로 개발되어진 모듈을 수정하던중 생각지도 않는 문제가 발생했습니다.


문제가 되는 기본 전제는 이러합니다. 부모의 기본생성자가 없다라는 점과 

자식 클래스에서는 이 부모 클래스를 상속받아 생성자를 오버라이딩해서 사용한다라는 점입니다.


여기서 부모 클래스 생성자에서는 메모리 할당을 하고 오버라이딩된 자식 클래스 생성자에서

이를 다시 메모리 할당하고자 할때 메모리 누수가 발생하였습니다. 지금 생각해도 참으로 복잡한 문제이죠...

에러가 난 코드를 최대한 간소화 시켜보았습니다.


//
// 메모리 누수 확인 코드
//
#ifdef _DEBUG
#include <crtdbg.h>
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

//
// Class A
//
class A {
public:
	char* szA;

public :
	A::A(int a)
	{
		szA = new char[a];

		OutputDebugString(_T("A생성자 호출\n"));
	}

	A::~A()
	{
		delete [] szA;

		OutputDebugString(_T("A소멸자 호출\n"));
	}
};

//
// Class B
//
class B : public A {

public:
	B::B(int b)
		// 1.
		// 부모가 기본생성자를 갖고있지 않으므로 자식은 생성자를 만들기 위해서
		// 부모의 사용가능한 생성자를 직접 지정해주어야 한다.
		: A(b)		
	{
		// 2.
		// 부모에서 생성된 객체를 메모리 할당
		szA = new char[b];

		OutputDebugString(_T("B생성자 호출\n"));
	}

	B::~B()
	{
		// 3.
		// 할당한 메모리를 제거하려 했으나 에러 발생
		// 여기서 메모리 누수 발생
		// delete [] szA;

		OutputDebugString(_T("B소멸자 호출\n"));
	}
};

//
// Main Function
//
int _tmain(int argc, _TCHAR* argv[])
{
#ifdef _DEBUG
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif

	A a(3);
	B b(3);	// 메모리 누수 발생

	return 0;
}


이를 해결하고자 다음과 같이 Class B를 수정하였습니다.

  
//
// Class B
//
class B : public A {

public:
	B::B(int b)
		// 1.
		// 부모가 기본생성자를 갖고있지 않으므로 자식은 생성자를 만들기 위해서
		// 부모의 사용가능한 생성자를 직접 지정해주어야 한다.
		: A(b)		
	{
		// 4.
		// 지정해준 [: A(b)] 부모 생성자에서 할당했던 객체를 미리 해제하고
		// 해당 생성자에서 할당된 객체는 이후 A소멸자가 호출될때 제거하게 해준다.
		delete [] szA;

		// 2.
		// 부모에서 생성된 객체를 메모리 할당
		szA = new char[b];

		OutputDebugString(_T("B생성자 호출\n"));
	}

	B::~B()
	{
		// 3.
		// 할당한 메모리를 제거하려 했으나 에러 발생
		// 여기서 메모리 누수 발생
		// delete [] szA;

		OutputDebugString(_T("B소멸자 호출\n"));
	}
};


'개발이야기 > C, C++' 카테고리의 다른 글

C언어 pthread 사용 방법  (0) 2014.03.05
포인터 배열 테스트 코드  (0) 2012.08.07
C코드 메모리릭 잡기  (0) 2012.07.18
마방진 원리 및 문제  (4) 2012.05.19
Mangled Name  (0) 2012.05.13