2009-02-20 1 views
5

System.GetMem과 System.ReallocMem의 차이점은 무엇입니까?GetMem x ReallocMem

ReallocMem 용 Delphi 2009 Help는 GetMem과 정확히 같은 설명입니다. System.FreeMem 및 System.Dispose는 어떻습니까

배열에는 무엇을 사용해야합니까?

type 
    PMemberDataList = ^TMemberDataList; 
    TMemberDataList = array[0..MaxClassMembers -1] of PMemberData; 

var 
    FItems: PMemberDataList; 

begin 
    GetMem(FItems, Value * SizeOf(Pointer)); 
    FreeMem(FItems); 
end; 

또는

begin 
    ReallocMem(FItems, Value * SizeOf(Pointer)); 
    Dispose(FItems); 
end; 

솔루션명의 조언 후, 레코드 유형으로 FItems는, 동적 배열, SetLength를 같이 TMemberDataList을 기록 포인터하지 선언

(드) 배열 배열, 데이터에 새로 만들기/삭제하기

type 
    PMemberDataList = ^TMemberDataList; 
    TMemberDataList = array of PMemberData; 
var 
    Items: TMemberDataList; 
    Item: PMemberData; 

// Add 
begin 
    Setlength(Items, 1); 
    New(Item); 
    Items[0]:= Item 
end; 

// Remove 
begin 
    Dispose(Items[0]); 
    Setlength(Items, 0); 
end; 
+0

업데이트 된 사용법에 따라 배열이 구성원 데이터를 "소유"한 것처럼 보입니다. 구성원 데이터 레코드를 가리키는 대신 PMemberData 대신 TMemberData의 배열을 만들어 코드를 단순화 할 수 있습니다. –

답변

20

GetMem은 항상 메모리를 할당하고 FreeMem은 항상 메모리를 해제하거나 해제하며 ReallocMem은 메모리를 할당하거나 다른 메모리를 해제합니다. 실제로 ReAllocMem이 제대로 사용되면 메모리 관리 API 만 필요합니다. nil 포인터로 시작하고 크기가 0보다 큰 ReAllocMem을 호출하면 GetMem처럼 작동합니다. 크기가 0 인 ReAllocMem을 호출하면 FreeMem처럼 작동합니다. 실제로 포인터가 non-nil이고 크기가 0보다 큰 경우에만 실제로 메모리를 "다시 할당"합니다.

New 및 Dispose는 입력 포인터 또는 "오래된 skool"사람들을 위해 설계되었습니다. . 이전의 터보 파스칼 개체 모델 (이전 "개체) 구문 신규 및 폐기는 어떤 관리 유형에 대한 참조가 제대로 유형을 초기화 할 것이다 포인터를 입력했는지 확인합니다 예를 들어 다음 주어진 :.

type 
    PMyRec = ^TMyRec; 
    TMyRec = record 
    Name: string; 
    Value: Variant; 
    end; 

var 
    Rec: PMyRec; 
begin 
    New(Rec); 
    try 
    Rec.Name := 'TestValue'; 
    Rec.Value := 100; 
    ... 
    finally 
    Dispose(Rec); 
    end; 
end; 

New 및 Dispose는 레코드의 이름 및 값 필드가 올바르게 초기화되고 정리되거나 정리 된 것을 보장합니다. 위의 경우 New 및 Dispose는 다음과 같습니다.

GetMem(Rec, SizeOf(Rec^)); 
Initialize(Rec); 
... 
Finalize(Rec); 
FreeMem(Rec); 

예를 들어, Gamecat이 맞다면, 동적 배열을 사용하는 것이 더 낫습니다. 컴파일러가 더 잘 관리하고 자체 고유 길이를 가지고 있기 때문입니다.예를 들어 배열의 항목 수를 따로 추적해야하므로 배열을 전달할 때마다 현재 할당 길이를 전달해야합니다. 동적 배열을 사용하면 모든 정보가 함께 깔끔하게 패키징됩니다. 이것은 단순히 다음 중 하나를 수행하여 관계없이 현재 길이의 배열을 반복 할 수 있도록합니다 :

var 
    Member: TMemberData; 
    Items: array of TMemberData; 
    ... 
begin 
    SetLength(Items, Value); 
    for Member in Items do // iterate over each element in the array 
    ... 
    for Low(Items) to High(Items) do // same as above only using std functions 
    ... 
end; 

마지막으로, 당신은 아마 동적 배열을 사용하고자 할 또 다른 이유가를 그 TMemberData 문자열, 변형 포함 된 경우 , 인터페이스 또는 다른 "관리되는"유형의 경우,이를 수동으로 할 필요없이 올바르게 초기화되고 완료됩니다.

+5

@Allen : 답변은 Delphi 도움말에 추가되어야합니다. –

+1

동의. (또 다시 Delphi 도움말에 추가해야 할 많은 것들이 있습니다!) : P –

+0

초기화 및 마무리 호출에서 Rec을 참조 해제해야합니다. 그들은 다르게 아무것도하지 않습니다. 컴파일러는 적어도 그것에 대해 경고합니다. –

3

GetMem은 메모리 블록을 할당합니다. ReallocMem은 메모리 블록을 다시 할당합니다.

하지만 당신은 더 나은 사용하는 동적 배열 :

var 
    FItems : array of TMemberDataList; 

begin 
    SetLength(FItems, Value); 
end; 

그것의 더 델파이 방법.

당신은 할 수 중 하나를 수행합니다

type 
    TMemberDataList = array[0..MaxClassMembers -1] of TMemberData; 

var 
    FItems: TMemberDataList; 
begin 
    // Don't need to allocate FItems 
end; 

또는 :

type 
    TMemberDataList = array of TMemberData; 

var 
    FItems: TMemberDataList; 
begin 
    SetLength(FItems, MaxClassMembers); 
end; 

클래스 변수에 대한 포인터입니다. 따라서 우리는 TP와 관련하여 명시 적 포인터를 사용할 필요가 없습니다. 레코드 나 오브젝트에 대한 포인터를 사용할 수는 있지만 그렇게 할 이유는 없습니다.

+0

@Gamecat :이 경우, 메서드 매개 변수로 전달하려면 var로 PMemberDataList가 필요합니다. 코드 : SetLength (FItems^[I] ^. ClassItems ^, Size); 예외가 발생합니다. [DCC 오류] JazzIntrospector.pas (433) : E2008 호환되지 않는 형식 –

+0

FItems가 정의 된 방법을 모르지만 명시 적 포인터가 필요하지 않습니다. (예를 들어) –

+0

내 질문에 코드처럼 정의되어 있습니다. 메서드 param으로 TMemberDataList를 전달하려고하면 컴파일러가 불평합니다. –