메모리 할당과 초기화는 다르다 :: 2007/12/14 18:01
|
|
string* p = new string[1024];
위와 같이 해서 메모리를 잡는 경우를 생각해 보죠. string에는 기본 생성자(default constructor)가 정의되어 있으니까 괜찮습니다만, 사실 이 방법은 "기본 생성자가 정의되어 있지 않은 타입"에는 적용할 수 없는 방법입니다. 심심하시면 기본 생성자를 정의하지 않고 다른 생성자만 정의해 둔 사용자 정의 타입에 대해서 배열로 메모리를 잡아 보세요. 컴파일 시 에러납니다. -_-
그렇다면 기본 생성자를 반드시 정의해 주어야 하느냐... 하는 고민에 빠지게 될텐데요. 물론 여러분이 만들어 놓은 타입의 경우에는 "기본 생성자가 정의되어 있지 않아서 생긴 문제를 푸는 가장 간단한 방법은 기본 생성자를 정의하는 것이다"라는 원칙에 입각하여, 기본 생성자 코드를 추가해 문제를 해결할 수 있습니다. 그런데, 기본 생성자를 추가하는 것이 아무리 봐도 불합리한 클래스를 사용하고 있는 경우나, 남이 만들어 놓은 클래스를 쓰는 경우에는, 기본 생성자를 추가할 수 없으므로, "배열을 선언할 수 없다"는 문제에 봉착하게 됩니다. 이런 문제를 둘러가는 가장 간단해 보이는 방법은 아마 아래와 같이 코드를 작성하는 것일 겁니다.
string *p = static_cast<string*>( ::operator new ( sizeof(string) * 1024 ) );
위와 같이 해서 메모리를 잡으면 분명 메모리를 잡을 수 있습니다!
하지만 한가지 주의할 것은, 이렇게만 하면 "메모리는 잡혔으나 객체는 생성되지 않는다"는 겁니다. 위의 코드는 메모리 청크를 잡아서 그에 대한 포인터를 그냥 p에 집어 넣은 것에 불과해요. 그러니 객체 초기화에 대한 부분을 어떻게 든 해 주어야 합니다. 어떻게 하는 것이 좋을까요? 네. 답을 아시는 분들도 있겠습니다만, 'placement new'를 사용하면 됩니다.
for ( unsigned int i = 0; i < 1024; ++i ) {
new ( &p[i] ) string ( "" );
}
위의 코드는 무슨 뜻입니까? &p[i]가 가리키는 메모리에 string 타입의 객체를 잡으라는 뜻이죠. placement new 를 쓰면, 객체의 초기화는 이루어지지만 메모리는 잡지 않습니다. new 연산자에 인자로 전달된 주소에 메모리가 잡혔다고 가정하게 되죠.
자. 그럼 이제 모든 문제가 다 해결된 건가요? 일단 이번 글에서 하고자 한 이야기는 여기까지 해서 다 전달한 것 같습니다. 그런데, 여기까지만 하고 잊어버리게 되면 또다른 문제가 생길 수 있어요. 메모리 반환에 대한 문제죠. delete [] p 하면 되나요?
통상적으로는 delete[]를 호출하면 p 가 가리키는 배열 내의 모든 원소에 대해서 소멸자가 호출된 다음에 메모리가 반환되죠. 될거 같기도 하죠? 그런데 이상한 문제가 생길 가능성이 생기게 됩니다. 메모리를 할당할 때 ::operator new를 썼기 때문에, 이 메모리는 1바이트 짜리 배열이지 sizeof(string) 크기 원소를 갖는 배열이 아니에요. 그러니 delete[] p와 같이 p의 타입에 종속적인 반환 연산을 하게 되면 문제가 생길 수 있게 됩니다. 두 연산 간에 bookkeeping 정보가 다를 수 있거든요. 그러니까 반환 할 때도 어쩔 수 없이 ::operator delete ( p )를 호출해야 합니다.
그런데 ::operator delete는 메모리만 반환하지 소멸자는 불러주지 않거든요. 여기에 또 문제가 있죠. 그러니까 ::operator delete를 쓸려면 소멸자를 일일이 명시적으로 불러줘야 하죠.
for ( unsigned int i = 0; i < 1024; ++i ) {
p[i].~string();
}
::operator delete( p );
그러니 이런 스타일의 코딩은 가급적 하지 않는 것이 좋겠습니다... 만 STL을 구현하신 분들은 이런 테크닉을 꽤 많이들 쓰셨다고 합니다. STL같은 거대 라이브러리를 설계하고 구현하는데 일반적인 C++ 코딩 가이드라인만 지켜서는 어렵겠죠. 아무튼, 이런 코딩을 할 일이 많이 생기지 않기를 바라는 수 밖에요. X-)
|
|





