흔히 배열로 할당받은 메모리는 delete[] 로 해제하고, 단일 객체로 할당받은 메모리는 delete 로 해제한다고 알고 있습니다.
이것이 정답이며, 이외의 꽁수를 부리는 것은 문제를 발생시킵니다.
습관적으로 늘 이렇게 짝을 맞춰서 사용했지만, 그래도 정확하게 문제를 아는 것이 중요하다고 생각됩니다.
우선 delete 와 delete[]의 차이를 한마디로 말하라면
delete 는 단일 객체에 대한 소멸자의 호출과 메모리 환원을 하며
delete[] 는 배열객체에 대한 각각의 소멸자의 호출과 메모리 환원을 한다는 것입니다.
그러므로
ClassA *pp = new ClassA;
delete pp;
는 아무런 문제가 없으나
ClassA *pp = new ClassA[10];
delete pp;
과 같이 하는 경우는 pp[0]에 대한 소멸자와 메모리 해제만 이루어 집니다.
반드시
ClassA *pp = new ClassA[10];
delete[] pp;
와 같이 해야 합니다. 그렇지 않으면 메모리 누수가 발생합니다.
혹자는 그냥 delete 만 써도 아무런 문제가 없다라고 말합니다.
이는 프로그램 종료시 할당받았던 전체 메모리가 OS에 의해 해제되기 때문입니다.
즉 메모리에 민감한 프로그램이 아닌 경우이겠지만, 정밀한 프로그램에서는 반드시 짝을 맞춰야 합니다.
실제 눈으로 확인을 해 봅시다.
다음은 테스트코드입니다. C++빌더의 테스트코드이긴 하지만 이해에 어려움은 없을 것입니다.
void add(void *ptr)
{
ULONG p = (ULONG)ptr;
Form1->Memo1->Lines->Add(String().sprintf("%08X", p));
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
class A
{
private:
void *p;
public:
A(void *ptr = 0)
{
p = ptr;
add(this); // 메모리 할당 받은 직후 자신의 메모리 베이스 어드레스를 표시하게 합니다.
}
~A()
{
int k = 0; // for trace
}
};
A *p = new A[2];
delete[] p; //***** 이 라인이 문제입니다.
A *p1 = new A;
delete p1;
}
위 코드는 아무런 문제가 없습니다.
제 컴퓨터에 실행해서 힙 메모리 할당 번지를 보면
00D16D00 // p[0] 꺼
00D16D04 // p[1] 꺼
00D16D0C // p1 꺼
이렇게 주소가 나옵니다.
여러번 실행해도 같은 주소만 계속 나옵니다. 메모리 할당과 해제가 완전하게 이루어진다는 뜻이죠.
그러면 delete[] p; 문장을 delete p; 로 바꾸고 실행해 보겠습니다.
처음 3개는 위와 같습니다.
00D16D00
00D16D04
00D16D0C
두번째로 함수가 다시 실행할때는 해제되지 못한 메모리로 인해 그 뒷번지에서 할당 받습니다.
00D16D10
00D16D14
00D16D1C
세번째도 마찬가지입니다. 이런식으로 메모리 잠식이 일어납니다.
00D16D20
00D16D24
00D16D2C
프로그램을 종료하고 다시 실행해 봅니다.
역시 위와 똑 같은 메모리 번지가 출력됩니다. 해제되지 못한 메모리가 OS에 되돌려졌다는 것을 알수 있습니다.
그럼..
|