C,C++

Delete 연산자

노력하는우리 2021. 3. 14. 00:05

Delete 연산자에 대해 알아보자

 

int* intPtr = new int;

int* intAry = new int[10];

 

이렇게 동적할당을 받았다면 해제를 어떻게 해줘야할까?

 

1. 일반 메모리 할당 받은것은 반드시 delete를 해주고 배열 메모리 할당 받은 것은 반드잇 delete[]를 해줘야 한다.

2. 별 상관없다.

 

정답은 2번이다.

 

그렇다면 delete와 delete[]는 왜 따로 나누어 놓은 것 일까?

 

객체를 메모리 해제할 때는 중요해지게 된다.

그것도 아무 객체가 아닌 "소멸자를 가지고 있는 객체"만 해당이 된다.

 

new []를 이용하여 객체를 할당 받으면 소멸자가 있을 경우 메모리 선두에 객체 배열의 갯수를 저장한다 (32비트 환경에서 4바이트, 64비트환경에서 8바이트) 그리고 우리에게는 배열 갯수를 제외한 선두에서 4가 더해진 주소를 반환한다.(32비트환경)

class Test

{

public:

~Test(){}

}

일 경우

Test *test = new Test[2];

했다고 가정했을때

| Test | Test | 의 선두를 우리에게 반환하지만 실제로 할당된 메모리는

|   2   | Test | Test | 이다.

그럼 선두에 배열 갯수는 왜 저장 하는 것 일까?

 

우리가 Delete[]를 했을 때 내부적으로 4바이트(32비트환경) 앞으로 점프하여 배열의 갯 수를 확인 후 배열 갯수 만큼

반복문을 돌며 소멸자를 호출하게된다.

 

이런 이유로 소멸자가 있는 객체들에 delete를 사용 할 때는 주의를 기울이자

 

자 그러면 간단한 테스트를 해보자

 

우선 일반 동적 할당을 받은 객체를 배열로 할당해제를 해보자 결과는

소멸자가 미친듯 호출되게 된다.

이유는 delete[]가 우리가 던저준 주소의 4바이트 앞(32비트환경) 주소를 체크하여 거기에 들어있는 값 만큼 반복문을 돌며 소멸자를 호출하는데 그 4바이트 앞 주소에는 쓰레기 값이 들어있기 때문이다.

 

Test* test = new Test;를 Test* test = new Test[1]; 로 변경해주는 것으로도 소멸자는 한번만 호출되게 된다.

 

반대인 경우도 알아보자. 

이 경우 메모리를 해제할때 에러가 발생한다 그 이유는 할당한적 없는 주소를 내부에서 free()하고 있기 때문이다.

선두에 4바이트를 배열 갯수에 저장후 배열 갯수를 제외한  부분 부터 주소를 반환 했기때문이다.

그렇다면 강제로 캐스팅을 해서 4바이트 앞 주소를 delete에 줘보자 

이렇게 하면 문제 없이 해제가 된다.

단 소멸자가 호출되지 않는다.

 

결론은

 

소멸자가 있는 객체를 동적 할당 받았을 경우

 

delete와 delete[]를 잘 구분해서 쓰자이다.