new 연산자를 사용한 동적 메모리 할당 실패시 예외 처리
new 실패에 따른 프로세스 종료원인을 찾다가 좋은 정보를 찾았습니다.
블로깅...
출처 : http://kuaaan.tistory.com/123
동적 메모리를 다음과 같이 사용하였습니다. 어디가 틀렸을까요?
- LPINT lpInt = NULL;
- lpInt = (LPINT)malloc(sizeof(INT));
- *lpInt = 4;
- printf("Value : %d\r\n", *lpInt);
- free(lpInt);
- LPINT lpInt = NULL;
- lpInt = (LPINT)malloc(sizeof(INT));
- if (lpInt == NULL)
- {
- printf("Fail to alloc memory!!\r\n");
- return FALSE;
- }
- *lpInt = 4;
- printf("Value : %d\r\n", *lpInt);
- free(lpInt);
- LPINT lpInt = NULL;
- INT nTotalBytes = 0, nAllocByte = 10000000;
- while(TRUE)
- {
- lpInt = NULL;
- lpInt = new INT[nAllocByte];
- nTotalBytes += nAllocByte * sizeof(INT);
- if (lpInt == NULL)
- {
- printf("Fail to alloc memory!!\r\n");
- break;
- }
- printf("Alloc Success!! (%d)\r\n", nTotalBytes);
- }
- // blah~ blah~
Beginning in Visual C++ .NET 2002, the CRT's new function (in libc.lib, libcd.lib, libcmt.lib, libcmtd.lib, msvcrt.lib, and msvcrtd.lib) will continue to return NULL if memory allocation fails. However, the new function in the Standard C++ Library (in libcp.lib, libcpd.lib, libcpmt.lib, libcpmtd.lib, msvcprt.lib, and msvcprtd.lib) will support the behavior specified in the C++ standard, which is to throw a std::bad_alloc exception if the memory allocation fails.
말하자면, new 연산자가 메모리 할당에 실패했을 경우, C++ 스탠다드에 따라 std::bad_alloc Exception을 throw한다는 의미입니다. exception이 throw되었기 때문에 넘겨받은 포인터가 NULL인지 체크하는 부분까지 진행되지도 않고 프로그램이 종료된 것입니다.
- try
- {
- LPINT lpInt = NULL;
- INT nTotalBytes = 0, nAllocByte = 10000000;
- while(TRUE)
- {
- lpInt = NULL;
- lpInt = new INT[nAllocByte];
- nTotalBytes += nAllocByte * sizeof(INT);
- printf("Alloc Success!! (%d)\r\n", nTotalBytes);
- }
- }
- catch ( exception e )
- {
- printf("%s\r\n", e.what( ));
- }
If the attempt is successful, the function returns a pointer to the allocated storage. Otherwise, the function calls the designated new handler. If the called function returns, the loop repeats. The loop terminates when an attempt to allocate the requested storage is successful or when a called function does not return.
The required behavior of a new handler is to perform one of the following operations:
Make more storage available for allocation and then return.
Call either abort or exit(int).
Throw an object of type bad_alloc.
The default behavior of a new handler is to throw an object of type bad_alloc. A null pointer designates the default new handler.
The order and contiguity of storage allocated by successive calls to operator new(size_t) is unspecified, as are the initial values stored there.
- void __cdecl MyNewHandler( )
- {
- printf("Fail to Alloc Memory \r\n");
- // throw bad_alloc();
- ExitProcess(FALSE);
- return;
- }
- int _tmain()
- {
- set_new_handler (MyNewHandler);
- LPINT lpInt = NULL;
- INT nTotalBytes = 0, nAllocByte = 10000000;
- while(TRUE)
- {
- lpInt = NULL;
- lpInt = new INT[nAllocByte];
- nTotalBytes += nAllocByte * sizeof(INT);
- printf("Alloc Success!! (%d)\r\n", nTotalBytes);
- }
- // blah~ blah~
- }
보통 C++ 개발자중에 상당수가 C언어를 접했을 것이다.
간혹가다보면^^ C++개발자들이 실수를 하는데,
바로 new연산자를 사용함에 있다.
char* buf;
buf = new char[100];
if(NULL == buf){
return FALSE;
}
이런식으로 사용하고 예외 처리를 하는데, 여기에는 문제점이 있다.
new연산자는 heap 메모리가 부족할 경우에는 NULL을 리턴하지 않는다.
할당을 실패할 경우에는 예외가 발생되어, if(NULL == buf)이 구문이 수행되지 않는다.
NULL체크 방식은 과거의 malloc을 사용했을 경우의 처리인 것이다.
C++에서는 이런 예외처리를 하기 위해 아래와 같이 #include <new>에 있는 bad_alloc객체를 이용해서
예외처리를 하고, NULL체크를 할수 있는 방식도 제공해준다.
#include <new>
#include <iostream>
using namespace std;
class BigClass {
public:
BigClass() {};
~BigClass(){}
#ifdef _WIN64
double BigArray[0x0fffffff];
#else
double BigArray[0x0fffffff];
#endif
};
int main() {
try {
BigClass * p = new BigClass;
}
catch( bad_alloc a) {
const char * temp = a.what();
cout << temp << endl;
cout << "Threw a bad_alloc exception" << endl;
}
BigClass * q = new(nothrow) BigClass;
if ( q == NULL )
cout << "Returned a NULL pointer" << endl;
try {
BigClass * r[3] = {new BigClass, new BigClass, new BigClass};
}
catch( bad_alloc a) {
const char * temp = a.what();
cout << temp << endl;
cout << "Threw a bad_alloc exception" << endl;
}
}
[출처] c++ new 연산자 예외 처리 (데브라이언 스튜디오) |작성자 성철임돠