본문 바로가기

Effective C++/3. 자원 관리

항목 16: new 및 delete를 사용할 때는 형태를 반드시 맞추자.

std::string *stringArray = new std::string[100];

delete stringArray;

 

 

여기서 잘못된 점이 보이냐? => 프로그램은 무조건 미정의 동작을 한다. why => stringArray 가르키는 100개의 string 객체 중에 99개는 제대로 소멸 과정을 거치지 못할 것이기 때문이다.

 

우리가 new 연산자를 사용해서 표현식을 꾸미게 되면(, new 어떤 객체를 동적 할당하면), 가지의 내부 동작이 진행된다.

  • 메모리가 할당된다.
  • 할당된 메모리에 대해 이상의 생성자가 호출된다.

 

delete 표현식을 경우에는

  • 기존에 할당된 메모리에 대해 이상의 소멸자가 호출된다.
  • 메모리가 해제된다.(이때 operator delete라는 이름의 함수가 쓰인다.)

 

 

 

밑의 그림이 핵심이다. new 만들어진 단일 객체와 new 만들어진 객체 배열이 다르기 때문이다. 객체 배열을 동적 할당하면 배열 앞에 배열의 길이가 들어간다. 반면 단일 객체용 메모리에는 이런 정보가 없다.

 

어떤 포인터에 대해 delete 적용할 , [] 사용하게 되면 delete '포인터가 배열을 가리키고 있구나' 라고 가정하게 된다. [] 붙여줘야 배열의 길이 정보를 참고하게 된다.

 

 

 

만약 delete stringArray1 [] 붙이면?? 만약 메모리 배치 구조가 그림처럼 되있으면 delete 앞쪽의 메모리 바이트를 읽고 이것을 배열 크기라고 해석한다. 이러고 배열 크기에 해당되는 횟수만큼 소멸자를 호출하게 된다. 그러다 결국 자신이 밟고 있는 메모리가 배열에 속해 있지도 않다는 사실은 물론, 메모리에는 자신이 소멸시키려는 타입의 객체가 이미 없다는 사실에 도달한다..

 

그럼 delete[] stringArray2 있는 [] 때면? 역시 정의된 바는 없지만 소멸자는 번만 호출될 것이다.

 

여튼 중요한거 : new 표현식에 [] 썼으면 delete 표현식에도 [] 쓰자.