new는 C++에서 객체의 메모리 할당과 생성자 호출을 통한 초기화를 담당합니다.
C의 malloc, calloc은 메모리 할당에 실패하게 되면 NULL을 리턴해줍니다.
하지만 new는 메모리 할당에 실패했을 때 NULL을 리턴하지 않습니다.
따라서 다음과 같이 예외 처리를 할 경우에는 정상적으로 동작하지 않습니다.
잘못된 코드
#include <iostream> using namespace std; void main() { char* pData = new char[0x7FFFFFFF]; if (nullptr == pData) { cout << "You can't reach here." << endl; return ; } delete[] pData; }
C++ 표준에서 new는 메모리 할당에 실패했을 때 std::bad_alloc 예외를 발생하도록 되어 있습니다.
MFC 환경에서는 CMemoryException를 리턴합니다.
예외가 발생된다면 처리는 try, catch를 통해서 가능합니다.
위의 코드는 다음과 같은 형식으로 수정해서 사용해야 합니다.
1. try-catch를 활용한 예외 처리
#include <iostream> using namespace std; void main() { char* pData = nullptr; try { pData = new char[0x7FFFFFFF]; } catch (bad_alloc ex) { cout << ex.what() << endl; return ; } delete[] pData; }
이제 정상적으로 실행이 가능합니다.
MFC 환경에서는 CMemoryException을 예외 처리하게 해줍니다.
Visual Assist X를 사용하시는 분들은 try만 쳐도 자동 완성을 통해서 예외 처리 구문을 작성해줍니다.
2. (std::nothrow)를 활용한 예외 처리
try-catch 구문이 번거롭게 느껴질 때는 new 뒤에 (std::nothrow)를 추가합니다.
(std::nothrow)가 추가될 경우 NULL을 리턴하는 기존의 방법으로 처리가 가능합니다.
다음과 같은 코드가 정상적으로 동작합니다.
#include <iostream> using namespace std; void main() { char* pData = new (nothrow) char[0x7FFFFFFF]; if (nullptr == pData) { cout << "You can reach here" << endl; return; } delete[] pData; }
3. new handler
set_new_handler라는 함수를 통해서 예외를 던지기 전에 사용자가 정의한 동작을 수행할 수 있도록 할 수 있습니다.
set_new_handler는 <new> 헤더에 선언되어 있습니다.
리턴이 없고 인자가 없는 함수 포인터를 받아들입니다.
다음과 같이 예외 처리가 가능합니다.
#include <iostream> #include <new> using namespace std; void MyFunc() { cout << "Do Something..." << endl; set_new_handler(nullptr); } void main() { set_new_handler(MyFunc); char* pData = nullptr; try { pData = new char[0x7FFFFFFF]; } catch (bad_alloc ex) { cout << ex.what() << endl; return; } delete[] pData; }
new는 메모리 할당에 실패할 경우 성공할 때까지 new를 반복해서 호출합니다.
set_new_handler로 설치한 처리자에서 set_new_handler(nullptr)을 호출하지 않으면
메모리 할당에 성공할 때까지 무한히 호출되기 때문에 내부에서 처리를 해줘야 합니다.
Effective C++에서는 set_new_handler로 설치한 처리자에서 다음과 같은 방법 중 하나를 선택하라고 합니다.
1. 사용할 수 있는 메모리를 더 많이 확보하라.
2. 다른 new 처리자를 설치하라.(위와 비슷한 방법이지만 MyFunc() 안에서 다른 new 처리자를 설치합니다.)
3. new 처리자의 설치를 제거하라.(위와 같은 방법입니다.)
4. 예외를 던져라.
5. abort()나 exit()를 호출해서 강제 종료하라.
C++의 new를 사용해서 메모리를 할당할 때는 위의 방법을 참고해서 예외처리를 진행하면 됩니다.
'Programming > C&CPP' 카테고리의 다른 글
wcout, wprintf 등에서 한글 출력 안될 때 해결법 (0) | 2015.01.19 |
---|---|
얕은 복사(Shallow Copy) vs 깊은 복사(Deep Copy) (0) | 2015.01.14 |
스마트하지 못한 스마트한 포인터 auto_ptr (0) | 2014.12.08 |
C++ 변환 연산자(Conversion operator) (0) | 2014.12.08 |
C++ 변환 생성자(Conversion Constructor) (0) | 2014.12.08 |