[Delphi] - Free vs FreeAndNil

Clover·2022년 3월 10일
0

Delphi

목록 보기
1/12
post-thumbnail

Free vs FreeAndNil

얼마전 작업한 프로젝트 코드의 메모리 관리 부분을 검토하다가 궁금증이 생겼다.
TObject.FreeSysutils.FreeAndNil 의 차이점이 무엇일까.

"Free vs FreeAndNil" 키워드로 구글링을 해보니, stackoverflow 질문 글이 가장 먼저 보였다.

Stackoverflow 질문글 : Free or FreeAndNil?

FreeFreeAndNil 을 각각 어떤 상황에서 사용해야 하는지, 둘의 차이점은 무엇인지.
라는 질문인데, 추천을 가장 많이 받고 채택도 받은 답변 내용을 짧은 영어 해석과 함께 정리해보았다.


FreeAndNil()

구현부

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

예제 및 설명

procedure TForm1.FormCreate(Sender: TObject);
var
  bm: TBitmap;
begin
  bm := TBitmap.Create;
  bm.LoadFromFile('C:\Users\User\Desktop\up.bmp');
  bm.Free;

  if Assigned(bm) then
    bm.SaveToFile('C:\Users\User\Desktop\test.bmp')
  else
    ShowMessage('Cannot save! The bitmap does no longer exist!');
end;

위 코드는 바탕화면에 텅 비어있는 bitmap 파일을 생성할 것이다.

  • 파일이 텅 비어있다.
    • bm 변수를 free 시켜줬기 때문.
  • showmessage를 출력하지 않고, 파일이 생성되었다.
    • 변수 bm은 여전히 메모리 주소를 point 하고 있는 assigned 상태이기 때문에, Assigned(bm)의 리턴값은 True이다.

이와 같은 에러를 피하기 위해서, 안전장치로 bm := nil;을 작성해넣으면 Assigned(bm)false값을 리턴할 것이다.

그래서 FreeAndNil(bm) 은, 아래 두 줄의 코드를 단축시켜 놓은 것이다.

  bm.free;
  bm := nil;
- 코드의 순서를 바꿔도 런타임 에러는 발생하지 않는다.

정리

결론은 객체가 해제가 되어 있더라도, 변수가 포인팅 하고 있는 메모리 주소까지 해제가 되는것은 아니기 때문에 Assigned()로 유효성 체크를 하고 넘어가려고 할 때 예상치 못한 Access violation을 마주하게 될 수도 있다는 것이다.

그러면 무조건 FreeAndNil()을 사용하는것이 좋은것인가? 그건 아닌 것 같다.
왜냐면 FreeAndNil() 자체가 에러가 나는 경우가 종종 있었기 때문인데.. (원인은 잘 모르겠다.)

결국 할당을 해제시킨 변수나 객체를 재사용 할 여지가 있는 경우에는 FreeAndNil()을 통해 "메모리 할당 해제"와 "초기화(Nil)"를 한번에 수행하는것이 런타임 에러 예방차원에서 좋다는 것이고, 그게 아니라면 Try ~ finally를 통해 Free;만을 수행하고 넘어가는것이 더 안정적일 수 있다는 것이다.

0개의 댓글