C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[603] 포인트의 안전한 해제를 위한 매크로.
김태선 [jsdkts] 8724 읽음    2006-05-05 14:02
C++에서는 객체에 대한 포인트는 객체가 할당된 메모리를 가르키는데,
객체를 메모리에서 해제시키는 부분에 대한 처리가 잘못되어 에러나는 경우가 많습니다.
그래서 안전한 객체의 할당과 해제는 C++ 플밍에서는  언제나 매우 중요한 문제입니다.
그 중에서 안전한 해제가 주요 문제이며 대부분의 에러는 객체를 해제하는 과정에서 나게 됩니다.

사실 C++처럼 드러내 놓고 포인트를 사용하지 않아도 다른 언어에서도 포인트를 사용하는
경우가 많으며, 포인트를 허용하지 않는 언어조차도 내부적으로는 포인트로 객체를 관리합니다.

델파이의 경우 객체의 안전한 해제를 위해 Free() 함수 외에 FreeAndNil() 함수를 지원합니다.
FreeAndNil 함수는 객체를 해제한 뒤 객체를 가르키는 포인트를 Nil 로 깨끗하게 클리어하여
다음번에 FreeAndNil이 다시 불려질 경우는 아무런 동작을 하지 않아, 객체가 해제된 메모리를
또 해제시킬때 나는 엑세스 바이올레이션 에러를 방지합니다.

C++에서도 이런 식으로 문제를 해결하기 위해 보통은 DELETE 같은 매크로를 나름대로 정의해서 사용합니다.
C++의 경우는 싱글 객체로 메모리를 할당받은 경우와 배열 객체로 메모리를 할당 받은 경우는
힙메모리의 정보가 다르게 기재되므로, 할당에 대한 해제 역시 다르게 해주어야 합니다.
특히 배열 객체의 경우 각 객체별로 소멸자가 불려지게 하기 위해서는 반드시 delete[] p; 식으로
배열 객체에 대한 메모리를 해제해 주어야만 합니다.

즉 단일 객체의 경우는
delete p;
로 해제해야 하고, 배열 객체의 경우는
delete[] p;
로 해제 합니다.

단일 객체이던 배열 객체이던, 그냥 delete p; 하나로 단일하게 메모리를 해제 해주었으면 좋겠는데,
이건 메모리를 할당 받는 구조가
C 에서 malloc 을 new 로 바꾸는 과정에서 C 의 방법을 그대로 이어 받았는데
구조상 어쩔수 없는 사항입니다.


필자가 사용하고 있는
단일 객체에 대한 FreeAndNil 매크로와
배열 객체에 대한 FreeArrayAndNil 매크로는 아래와 같습니다.
객체 소멸시 델파이는 Free 하지만  C++은 delete 하므로,
명칭도 아래와 같이 하는게 더 보기 쉬울 것입니다.

//---------------------------------------------------------------------------
// 포인트의 안전한 해제를 위한 매크로

#define DeleteAndNULL(p);        if (p) { delete p; p = NULL; }
#define DeleteArrayAndNULL(p);    if (p) { delete[] p; p = NULL; }



//---------------------------------------------------------------------------
// 사용예

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TForm *pForm = new TForm(Application);
    // do something....
    DeleteAndNULL(pForm);

    char  *str = new char[10000];
    // do something....
    DeleteArrayAndNULL(str);
}
//---------------------------------------------------------------------------


delete 를 직접 사용하는 것보다 위 매크로를 사용하면 프로그래밍중에
메모리를 두번 제거하는 일을 방지 할수 있으며, 확실하게 다 쓴 메모리에 대한 포인트는
NULL로 세팅되므로, 에러가 방지되고 구분하기 매우 좋습니다.

아주 간단한 팁이지만,
조금 규모 있는 플밍을 하자면 필수적으로 사용해야 할 매크로입니다.



참고로 델파이의 FreeAndNil 함수 코드입니다.

procedure FreeAndNil(var Obj);
var
    Temp: TObject;
begin
    Temp := TObject(Obj);
    Pointer(Obj) := nil;
    Temp.Free;
end;

함수명과는 달리 Nil And Free 하죠.
대부분 문제가 없지만, Thread에서 nil 을 넣은 순간 Free 이전에 포인트를 참조해야 하면 에러가 나게 됩니다.
그럼에도 이렇게 해 놓은 문제는 소멸자에서 에러가 나는 경우 Nil 값을 대입할 수 없기 때문에 미리 대입하고 Free시켜 소멸자를 호출하는 것입니다.
그러므로 쓰레드를 사용하는 경우는 약간 유의를 해야 하겠죠.
또 FreAndNil 함수의 경우 이미 해제된 경우에 대한 검사를 하지 않아, 수동으로 if Assigned(p) then 식으로
검사를 해줘야 합니다.
이건 델파이쪽 문제고요

위의 C++  매크로는 말그대로 Free And Null 이니 상관없지요.


그럼..
김태선 [cppbuilder]   2006-06-27 18:08 X
참고로 NULL 이 대입된 포인트 변수는 이후 delete 문장을 혹시 만나더라도 안전합니다.
가령 pNet = NULL; 로 되었는데,
프로그램의 어느 곳에서
delete pNet;
가 실행되어도 pNet 값이 0 이므로, delete는 아무런 동작도 하지 않습니다.


+ -

관련 글 리스트
603 포인트의 안전한 해제를 위한 매크로. 김태선 8724 2006/05/05
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.