Skip to content

C++:new

C++의 new 키워드에 대한 정리.

new 연산자의 예외 처리에 대한 오해

얼마전에 누군가가 작성한 소스에 다음과 같은 코드가 포함되어 있는 것을 발견하였습니다. 약 100MB 정도의 메모리를 할당한 다음 메모리 할당에 실패하였을 경우, 이에 대한 예외 처리를 하는 코드였죠.

char* ptr;
ptr = new char[100 * 1024 * 1024];
if (!ptr) {
    ...
}

얼핏 보면 이 코드는 전혀 문제가 없어보이지만, 사실 아주 큰 문제점을 가지고 있는 코드입니다. 왜냐하면 new 연산자가 실패한다고 하더라고 절.대.로. if 블록 안으로 진입하지 않기 때문이죠. 만약 이 코드를 보고도 전혀 이상한 점을 느끼지 못하셨다면...잠시 반성의 시간을 가지도록 합시다. ^^; (사실 new 연산자에 의한 메모리 할당이 실패하는 일은 거의 없기 때문에 위와 같은 코드에 대한 검증 없이 무심코 넘어가 버리는 경우가 많습니다.)

C++ 표준에 따르면 new 연산자의 메모리 할당이 실패할 경우 std::bad_alloc 타입의 예외를 발생시키도록 되어있습니다. 결국 위 코드에서도 메모리 할당에 실패하면 ptr 변수에 NULL이 리턴되는 것이 아니라 std::bad_alloc 타입의 예외가 발생하고, 이 예외는 어디에서도 처리되지 않아 프로그램이 비정상적으로 종료되겠죠. 그렇다면 new 연산자의 메모리 할당이 실패했을 경우의 예외 처리를 제대로 구현하려면 어떻게 해야할까요?

new 연산자의 올바른 예외 처리 방법 01: try-catch

당연한 얘기지만 가장 먼저 생각해 볼 수 있는 방법은 try-catch 구문을 이용하여 예외를 처리해주는 방법입니다. new 연산자를 사용하는 코드를 try 블럭으로 묶어주고, catch 구문에서 std::bad_alloc 타입의 예외를 처리하도록 구현하면 되겠죠.

char* ptr;
try {
    ptr = new char[0x7ffffffe];
} catch (std::bad_alloc e) {
    wcout << e.what() << endl;
}

참고로 MFC 환경에서는 std::bad_alloc 타입이 아닌 CMemoryException 타입의 예외를 발생시키기 때문에(operator new가 오버로드 되어있습니다) 아래와 같이 구현하셔야 합니다.

char* ptr;
try {
    ptr = new char[0x7ffffffe];
} catch (CMemoryException* e) {
    ...
}

new 연산자의 올바른 예외 처리 방법 02: new(std::nothrow)

'나는 try-catch 구문을 이용한 예외 처리 스타일이 영 맘에 들지 않는다' 하는 분들을 위한 방법입니다. new 대신 new(std::nothrow) 를 사용하면, 메모리 할당에 실패했을때 예외를 발생시키지 않고 NULL을 리턴하게 됩니다(이것 역시 C++ 표준에 명시되어 있습니다). 결국 new(std::nothrow) 를 사용할 경우에는 맨 위에서 작성했던 잘못된 코드와 유사한 스타일로 예외 처리를 구현할 수 있습니다.

char* ptr;
ptr = new(std::nothrow) char[0x7ffffffe];
if (!ptr) {
    ...
}

Dynamic memory managementLow level memory management

Favorite site