2017-09-26 17 views
0

다음과 같은 코드를 최대한 단순화하여 문제점을 보여주었습니다. 소멸자 TClass3.Destroy가 완료되면 FreeAndNil (FClass3) 작업으로 인해 문제가 발생하고 프로그램이 중지됩니다. Heap.trc 파일의 모습이 있다면 내가 잘못 $ 0000000001528FD0에서HeapTrc에서 잘못된 서명이 나타나는 이유는 무엇입니까?

마크 된 메모리를 읽을 수
잘못된 서명 $ 2951FD2D 대신

program Project_testFree; 
{$mode objfpc}{$H+} 

uses 
    sysutils; 

type 
    TClass1 = class 
    private 
    protected 
    public 
    constructor Create; 
    end; 

    TClass2 = class(TClass1) 
    private 
    protected 
    FTClass2 : cardinal; 
    public 
    end; 

    TClass3 = class 
    private 
    protected 
    FClass3  : TClass1; 
    public 
    constructor Create;virtual; 
    destructor Destroy;override; 
    end; 

    TClass4 = class(TClass3) 
    private 
    function GetLocalClass2: TClass2; 
    protected 
    public 
    constructor Create;override; 
    destructor destroy;override; 
    property pClass2:TClass2 read GetLocalClass2; 
    end; 

constructor TClass1.Create; 
begin 
    inherited; 
end; 

constructor TClass3.Create; 
begin 
    FClass3    := TClass1.create; 
end; 

destructor TClass3.Destroy; 
begin 
    FreeAndNil(FClass3); 
    writeln('Destroy'); 
    inherited Destroy; 
end; 

constructor TClass4.Create; 
begin 
    inherited Create; 
    pClass2.FTClass2 := 1; 
end; 

destructor TClass4.destroy; 
begin 
    inherited destroy; 
end; 

function TClass4.GetLocalClass2: TClass2; 
begin 
    result := TClass2(FClass3); 
end; 

var 
    c:TClass4; 
begin 
    if FileExists('heap.trc') then 
    DeleteFile('heap.trc'); 
    SetHeapTraceOutput('heap.trc'); 

    c:=TClass4.Create; 
    c.free; 
end. 

5C063D8B

나는 나사로 1.6.2 사용합니다. 도움 주셔서 감사합니다.

+0

코드에 의한 힙 손상? 어쨌든이 문제는 아마도 문제와 관련이 없지만 파일 이름에 항상 명시 적 절대 경로를 포함해야합니다. – MartynA

+0

내 문제와 관련이없는 것 같아요. 내 응용 프로그램의 같은 디렉토리에서 파일을 가져 오려면 절대 경로가 필요하지 않다고 생각했습니다. –

+0

응용 프로그램의 디렉토리에 대한 쓰기 권한이 있다고 가정합니까? – MartynA

답변

3

FClass3TClass2으로 캐스팅합니다. 하지만 TClass1을 인스턴스화했습니다. 따라서 오류를 설명하는 캐스트가 올바르지 않습니다. 본질적으로, 당신은 컴파일러에게 거짓말을했고, 그것은 그것의 복수를 요구했습니다.

as을 사용하여 체크 된 캐스트를 사용했다면 런타임 오류가 발생했을 것입니다.

+0

너는 맞아. 데이빗, 나는 그것을 보지 못했다. 나는 확실하게 몰두하지 않는 한 가지 중요한 것을 기억할 것이다. 'as'를 사용하여 작성하면 오류가 발생합니다. 나는 ** constructor TClass4.Create와 같은 코드를 재 배열 할 것이다. 상속 된 Create 시작; FLocalClass2 : = TClass2.Create; FLOcalClass2.FTClass2 : = 1; 종료; 소멸자 TClass4.destroy; FreeAndNil (FLocalClass2)를 시작하십시오. 상속 된 파괴; 끝 ** ** –

+0

당신은 클래스의 이름을 정렬해야합니다. 또한 인스턴스 클래스의 이름을 지정하지 않아야합니다. –