Witam, poniżej mam pewien przykładowy kod:
type
TTestClass = class
Argument: Pointer;
procedure GetData;
procedure MainProc;
end;
TChars = array of Char;
procedure TTestClass.GetData;
var
S: string;
A: TChars;
begin
S := 'Some data :)'#0;
SetLength(A, Length(S));
Move(S[1], A[0], Length(S));
Self.Argument := A; // <-- X
end;
procedure TTestClass.MainProc;
var
A: TChars;
begin
Self.GetData;
A := Self.Argument; // <-- X
ShowMessage(PChar(A)); // <-- access violation
A := nil;
end;
powoduje on access violation w oznaczonej linii.
Jeżeli linie oznaczone literą X zamienimy na takie:
Self.Argument := Pointer(A);
Pointer(A) := Self.Argument;
to niby wszystko działa ale access violation pojawia się po zamknięciu formy.
Dopiero takie linie:
TChars(Self.Argument) := A;
A := TChars(Self.Argument);
działają poprawnie.
Pytanie jest następujące: dlaczego? Zawsze myślałem, że rzutowanie jest tylko po to żeby kompilator miał pewność, że wiem, co robię natomiast dane pozostają na swoim miejscu. Dlaczego w tym przypadku rzutowanie ma znaczenie?
Pytanie dodatkowe. Czy jeśli w funkcji F zadeklaruje zmienną lokalną S typu string i przypisze do niej ciąg znaków, a następnie ustawię globalny wskaźnik P na S, to czy po zakończeniu funkcji F, mimo tego że P nadal wskazuje na S, to string S zostanie zwolniony? Bo rozumiem, że tablica dynamiczna na pewno nie zostanie zwolniona dopóki się tego samemu nie zrobi a jak jest ze stringiem?