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 표현식에도 []를 쓰자.
'Effective C++ > 3. 자원 관리' 카테고리의 다른 글
항목 17: new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자. (0) | 2021.04.24 |
---|---|
항목 15: 자원 관리 클래스에서 관리하는 자원은 외부에서 접근할 수 있도록 하자 (0) | 2021.04.24 |
항목 13: 자원 관리에는 객체가 그만! (0) | 2021.04.24 |