C에서는, 메모리의 할당과 해제를 위해 malloc()과 free()를 비롯한 malloc()계열의 함수를
쓰지만, 다들 단점을 갖고 있다.
그래서 C++ 은 메모리를 다루기 위한 연산자들을 도입했고, 이들은
new 와 delete이다.
이 연산자들은 실행시에 힙(heap - 혹은 자유 공간)으로부터 메모리를 할당, 해제한다.
C++에서는 정말로 꼭 malloc()이나 free()만을 써야하는 상황이 아니라면 언제나
new 와 delete를 써야한다.
그러나 주의할 점은, 이 두 가지를 섞어서 쓰면 안된다는 것이다.
malloc()으로 얻은 메모리를 delete로 해제할 수는 없고, 반대로 new로 얻은 메모리를
free()시킬 수도 없다.
9.1. C++ Zap (Delete) 함수
C++에서의
delete 와 new
연산자는 C의 malloc, free보다 낫다. 따라서 malloc과 free 대신 new와 zap(delete)를
쓰도록 하는 것이 좋다.
delete 연산자가 좀 더 깔끔하게
사용되게 하기위해 다음과 같은 Zap() inline 함수를 만들자.
다음과 같이 zap()을 정의하자.
// x가 NULL인지 체크하기 위해 assert를 사용하였다.
// 이는 프로그램의 "논리적" 에러를 미리 잡아내기 위한 것이다.
// delete가 NULL인 경우에도 잘 동작하긴 하지만, assert를
// 사용함으로써 좀 더 일찍 에러를 잡아낼 수 있다.
// Zap을 template을 사용하여 정의하자.
// delete대신 zap을 사용하면 더 깔끔할 것이다.
template <class T>
inline void zap(T & x)
{
{assert(x != NULL);}
delete x;
x = NULL;
}
// C++에 두 가지 delete 연산자의 용법이 있는 이유는 C++ 에게
// 한 객체에 대한 포인터와 객체의 배열에 대한 포인터를 구별하도록
// 말해주는 방법이 필요하기 때문이다.
// delete연산자는 프로그래머에게 "[]"를 쓰게함으로써 이를 구별한다.
// 따라서 우리는 포인터의 배열을 지우기 위한 zaparr 함수를 다음과 같이 정의할 수 있다
template <class T>
inline void zaparr(T & x)
{
{assert(x != NULL);}
delete [] x;
x = NULL;
}
zap()함수는 포인터를 delete시키고 NULL로 세팅한다.
이는 똑같은 delete 포인터에 대해 여러번의 zap()이
불려서 프로그램이 망가지는 것을 방지한다.
다음의 zap_example()함수를 보아라.
example_String.cpp
'Source code of C++'을 클릭해라.
// example_String.cpp에서 zap_example()를 보라.
zap(pFirstname);
//zap(pFirstname); // pFirstname이 NULL이므로 코어 덤프가 일어나지 않는다.
//zap(pFirstname); // pFirstname이 NULL이므로 코어 덤프가 일어나지 않는다.
zap(pLastname);
zap(pJobDescription);
int *iiarray = new int[10];
zaparr(iiarray);
뭐 특별한 것이 있는 것은 아니고, 이것은 단지 반복적인 코드를 줄이고
타이핑하는 시간을 아껴주며 프로그램을 좀 더 읽기 좋게 만들어주는 것 뿐이다.
C++ 프로그래머들은 자주 delete한 pointer를 NULL로 세팅하는 것을 잊는다.
그리고 이는 코어덤프와 오작동으로 이어질 수 있다.
zap()은 이러한 문제를 자동으로 처리해준다.
zap()에 타입 캐스팅을 할 필요는 없다. 만약 위 zap()함수에서 에러가 난다면,
다른 데서 시작된 에러일 것이다.
또한
9.2절
, my_realloc() 과 my_free() 이
malloc(), realloc() 그리고 free() 대신 쓰여야 한다.
이들은 훨씬 깔끔하고, 여러가지 체크도 해준다.
예를들어,
9.2절 과
my_free() 함수를 사용하는 "String.h" 파일을 보라.
주의 :
'new'로 할당된 메모리를 해제하기 위해 free()를 쓰거나, malloc()으로 할당된
메모리를 해제하기 위해 'delete'를 쓰지 말아라. 그렇지 않으면
결과를 예측할 수 없는 에러에 빠질 것이다.
malloc과 realloc 을 최대한 사용하지 말고, new 와
9.1절(delete)을 사용해라.
그러나 때로는 C++에서 C 스타일의 메모리 할당을 사용해야 할 필요도 있다.
이 때는 my_malloc() ,
my_realloc() ,
my_free() 을 사용해라.
이 함수들은 적절한 할당과 초기화를 해주고, 메모리 문제를 예방해준다.
또한 이 함수들은 DEBUG모드에서 메모리 할당을 추적해주고, 프로그램 실행
전후에 총 메모리 사용량을 표시해준다. 이는 메모리 릭이 있는지를
알려줄 것이다.
my_malloc 과 my_realloc은 다음과 같이 정의되었다.
이는 약간의 메모리를 더 할당해서 (SAFE_MEM = 5) 초기화시키고,
메모리를 할당할 수 없으면 프로그램을 종료한다.
'call_check(), remove_ptr()' 함수는 DEBUG_MEM 가 makefile에서
((void)0) (이는 NULL을 의미한다)으로 지정되어있을 때에만 작동한다.
이는 총 메모리 사용량을 추적할 수 있게 해준다.
void *local_my_malloc(size_t size, char fname[], int lineno)
{
size_t tmpii = size + SAFE_MEM;
void *aa = NULL;
aa = (void *) malloc(tmpii);
if (aa == NULL)
raise_error_exit(MALLOC, VOID_TYPE, fname, lineno);
memset(aa, 0, tmpii);
call_check(aa, tmpii, fname, lineno);
return aa;
}
char *local_my_realloc(char *aa, size_t size, char fname[], int lineno)
{
remove_ptr(aa, fname, lineno);
unsigned long tmpjj = 0;
if (aa) // aa != NULL
tmpjj = strlen(aa);
unsigned long tmpqq = size + SAFE_MEM;
size_t tmpii = sizeof (char) * (tmpqq);
aa = (char *) realloc(aa, tmpii);
if (aa == NULL)
raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
// do not memset memset(aa, 0, tmpii);
aa[tmpqq-1] = 0;
unsigned long kk = tmpjj;
if (tmpjj > tmpqq)
kk = tmpqq;
for ( ; kk < tmpqq; kk++)
aa[kk] = 0;
call_check(aa, tmpii, fname, lineno);
return aa;
}
char *aa;
int *bb;
float *cc;
aa = (char *) my_malloc(sizeof(char)* 214);
bb = (int *) my_malloc(sizeof(int) * 10);
cc = (float *) my_malloc(sizeof(int) * 20);
aa = my_realloc(aa, sizeof(char) * 34);
bb = my_realloc(bb, sizeof(int) * 14);
cc = my_realloc(cc, sizeof(float) * 10);
my_realloc 에서 data type을 cast 할 필요가 없는 것에 주의해라.
이는 인자로 받은 변수의 타입에 맞춰서 리턴값을 보내기 때문이다.
The my_realloc 함수는 char *, int *, float * 타입으로 오버로딩
되어있다.
9.3. C++ 에서의 가바지 콜렉터
C/C++에서 가비지 콜렉션은 표준에서 지원되지 않고, 따라서 메모리를 직접
할당, 해제하는 것이 어렵고 복잡하며 에러를 내기 쉽다.
가비지 콜렉션(GC:Garbage Collection) 은
구현하는 방법이 여러가지가 있고, 각 프로그램마다 적용될 수 있는 방법이
다르기 때문에 C++ 표준의 일부가 될 수 없었다.
전산학자들은 많은 GC 알고리즘을 개발했고, 이들은 각 문제분야에서만
적용될 수 있는 것들이었다.
즉, 모든 일반적인 문제에 적용될 수 있는 하나의 범용 GC알고리즘은 없다.
따라서 GC는 C++ 표준에 들어가지 못했다. 따라서 언제나 하는 일에 맞는
C++ 라이브러리를 많은 라이브러리들 중에서 고를 수 있다.
9. C++ 에서의 메모리 할당
C에서는, 메모리의 할당과 해제를 위해 malloc()과 free()를 비롯한 malloc()계열의 함수를 쓰지만, 다들 단점을 갖고 있다. 그래서 C++ 은 메모리를 다루기 위한 연산자들을 도입했고, 이들은 new 와 delete이다. 이 연산자들은 실행시에 힙(heap - 혹은 자유 공간)으로부터 메모리를 할당, 해제한다.
C++에서는 정말로 꼭 malloc()이나 free()만을 써야하는 상황이 아니라면 언제나 new 와 delete를 써야한다. 그러나 주의할 점은, 이 두 가지를 섞어서 쓰면 안된다는 것이다. malloc()으로 얻은 메모리를 delete로 해제할 수는 없고, 반대로 new로 얻은 메모리를 free()시킬 수도 없다.
9.1. C++ Zap (Delete) 함수
C++에서의 delete 와 new 연산자는 C의 malloc, free보다 낫다. 따라서 malloc과 free 대신 new와 zap(delete)를 쓰도록 하는 것이 좋다.
delete 연산자가 좀 더 깔끔하게 사용되게 하기위해 다음과 같은 Zap() inline 함수를 만들자. 다음과 같이 zap()을 정의하자.
zap()함수는 포인터를 delete시키고 NULL로 세팅한다. 이는 똑같은 delete 포인터에 대해 여러번의 zap()이 불려서 프로그램이 망가지는 것을 방지한다. 다음의 zap_example()함수를 보아라. example_String.cpp 'Source code of C++'을 클릭해라.
뭐 특별한 것이 있는 것은 아니고, 이것은 단지 반복적인 코드를 줄이고 타이핑하는 시간을 아껴주며 프로그램을 좀 더 읽기 좋게 만들어주는 것 뿐이다. C++ 프로그래머들은 자주 delete한 pointer를 NULL로 세팅하는 것을 잊는다. 그리고 이는 코어덤프와 오작동으로 이어질 수 있다. zap()은 이러한 문제를 자동으로 처리해준다. zap()에 타입 캐스팅을 할 필요는 없다. 만약 위 zap()함수에서 에러가 난다면, 다른 데서 시작된 에러일 것이다.
또한 9.2절 , my_realloc() 과 my_free() 이 malloc(), realloc() 그리고 free() 대신 쓰여야 한다. 이들은 훨씬 깔끔하고, 여러가지 체크도 해준다. 예를들어, 9.2절 과 my_free() 함수를 사용하는 "String.h" 파일을 보라.
주의 : 'new'로 할당된 메모리를 해제하기 위해 free()를 쓰거나, malloc()으로 할당된 메모리를 해제하기 위해 'delete'를 쓰지 말아라. 그렇지 않으면 결과를 예측할 수 없는 에러에 빠질 것이다.
example_String.cpp 에서 'Source code of C++' 를 클릭한다음, zap함수의 예를 보아라.
9.2. my_malloc 과 my_free 의 사용
malloc과 realloc 을 최대한 사용하지 말고, new 와 9.1절(delete)을 사용해라. 그러나 때로는 C++에서 C 스타일의 메모리 할당을 사용해야 할 필요도 있다. 이 때는 my_malloc() , my_realloc() , my_free() 을 사용해라. 이 함수들은 적절한 할당과 초기화를 해주고, 메모리 문제를 예방해준다. 또한 이 함수들은 DEBUG모드에서 메모리 할당을 추적해주고, 프로그램 실행 전후에 총 메모리 사용량을 표시해준다. 이는 메모리 릭이 있는지를 알려줄 것이다.
my_malloc 과 my_realloc은 다음과 같이 정의되었다. 이는 약간의 메모리를 더 할당해서 (SAFE_MEM = 5) 초기화시키고, 메모리를 할당할 수 없으면 프로그램을 종료한다. 'call_check(), remove_ptr()' 함수는 DEBUG_MEM 가 makefile에서 ((void)0) (이는 NULL을 의미한다)으로 지정되어있을 때에만 작동한다. 이는 총 메모리 사용량을 추적할 수 있게 해준다.
my_malloc 과 my_free 를 쓰는 예는 다음과 같다.
9.3. C++ 에서의 가바지 콜렉터
C/C++에서 가비지 콜렉션은 표준에서 지원되지 않고, 따라서 메모리를 직접 할당, 해제하는 것이 어렵고 복잡하며 에러를 내기 쉽다. 가비지 콜렉션(GC:Garbage Collection) 은 구현하는 방법이 여러가지가 있고, 각 프로그램마다 적용될 수 있는 방법이 다르기 때문에 C++ 표준의 일부가 될 수 없었다. 전산학자들은 많은 GC 알고리즘을 개발했고, 이들은 각 문제분야에서만 적용될 수 있는 것들이었다. 즉, 모든 일반적인 문제에 적용될 수 있는 하나의 범용 GC알고리즘은 없다. 따라서 GC는 C++ 표준에 들어가지 못했다. 따라서 언제나 하는 일에 맞는 C++ 라이브러리를 많은 라이브러리들 중에서 고를 수 있다.
다음 C++ 가비지 콜렉션(Garbage Collection) 사이트와 메모리 관리 사이트를 가보아라.
Recent Posts
Archive Posts
Tags