100jk 님이 쓰신 글 :
: 아래와 같은 소스가 있습니다.
:
: var
: b, b2: Tbitmap;
: begin
: b := tbitmap.create;
: b2 := b;
: b.free; //비트맵해제
: //{이곳에 판단식을 넣고싶습니다.}
: b2.free; //당연히 에러
:
: b2를 해제하기 전에 b2주소에 있는 비트맵(혹은 다른 클래스)이 이미 해제되어있는 상태인지
:
: 판단할 수 있는 방법이 있나요?
답변:
기술적인 부분이라 답변 남깁니다.
파일 생성과 삭제를 반복하다 보면 디스크 Fragment(단편화)가 발생하는 것과 마찬가지로
메모리도 할당과 삭제를 반복하게 되면 Fragment가 발생하게 되어...
Free 메모리 총합은 여유가 있어도, 메모리 할당에 실패하는 경우가 발생하게 됍니다.
1.5GB 프리 상태인데 AllocMem(1GB) 할당에 실패하는 경우 등.
메모리 메니지먼트 코드를 구현할 때...
1.
단편화를 최대한 줄이는 쪽으로 메모리를 효율적으로 사용할 수 있도록 하기위해 알고리즘 구현에
공을 들여서 구현하는 방법이 있고...
2.
메모리를 Small, Medium, Large로 Heap 블럭으로 나누어서 사용하되, Chaind Block 리스트로 Small Block 을
별도로 관리하는 간단한 방법으로 구현할 수도 있는데...
델파이 메모리 매니지먼트 내부코드는 2.번의 단순한 방법을 이용해서 구현되어 있습니다.
델파이 언어는 exception 발생 여부와 상관없이 메모리 같은 리소스를 안전하게 해제하기 위해
반드시 try... finally 블럭을 사용해야 하는 반면에, C++은 exception 발생 여부와 상관없이 RAII 패턴을 이용해서
리소스를 안전하게 해제할 수 있어서... 퍼포먼스 면에서는 C++이 훨씬 유리하지요.
본론으로 돌아와서...
할당되어 있던 메모리가 해제 됐는지 아닌지는 델파이 메모리 매니지먼트 내부구조를 이해하고 있으면
간단하게 알아 낼 수 있습니다.
memory management 내부구조는 델파이 버전에 따라 다를 수 있어서...
설치되어 있는 rad 10.3.1 기준으로 설명합니다.
function IsFreed(var obj ): Boolean;
begin
Result := PULONG_PTR(PByte(obj) - sizeof(ULONG_PTR))^ and 1 <> 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var b1, b2: TBitmap;
begin
b1 := TBitmap.Create;
b2 := b1;
b1.Free;
if IsFreed(b2) then
Memo1.Lines.Add('b2 freed.');
end;
위와 같이 처리하면 할당되어 있던 메모리의 해제여부를 쉽게 알아 낼 수 있습니다만...
std::shared_ptr 이용해서 C++로 코딩하면 공유 메모리 관리에 신경 쓸 일이 없지요.