Einzelnen Beitrag anzeigen

CalganX

Registriert seit: 21. Jul 2002
Ort: Bonn
5.403 Beiträge
 
Turbo Delphi für Win32
 
#1

SynEdit: EInvalidPointer beim Beenden

  Alt 11. Mär 2007, 15:05
Hi,
ich komme einer EInvalidPointer-Exception nicht auf die Schliche.
Ich verwendet die aktuellste Version von SynEdit (2.0.4 glaube ich) unter Turbo Delphi. D.h. ich erstelle sie dynamisch auf meinem Formular. Der Inhalt der SynEdits (genau genommen sind es zwei), werden hin und her geschoben und auch an eine Klasse weitergeleitet zu Verwendung.

Diese Klassen mal schematisch:
Delphi-Quellcode:
TWorker = class
private
  FSource: TStrings;
protected
  function GetSource: TStrings;
  procedure SetSource(const ASource: TStrings);
published
  property Source: TStrings read FSource write FSource;
end;

function TWorker.GetSource: TStrings;
begin
  Result := FSource;
end;

procedure TWorker.SetSource(const ASource: TStrings);
begin
  // Source-Code setzen
  if ASource <> nil then
    FSource.Assign(ASource);
end;
Delphi-Quellcode:
TInterpreter = class(TWorker)
protected
  function GetSource: TStrings;
  procedure SetSource(const Value: TStrings);
published
  property Source: TStrings read GetSource write SetSource;
end;

function TInterpreter.GetSource: TStrings;
begin
  Result := inherited GetSource;
end;

procedure TInterpreter.SetSource(const Value: TStrings);
begin
  inherited SetSource(Value);

  // Zurücksetzen
  EIP := 0;
  PrepareSource;
end;
Im Programm gibt es dann einige Zuweisungen:
Delphi-Quellcode:
procedure TfrmMain.Create(Sender: TObject);
begin
  // SynEdit erzeugen
  sedtSourceCode := TSynEdit.Create(tabEditCode);
  with sedtSourceCode do
  begin
    Parent := tabEditCode;
    Align := alClient;

    WordWrap := true;

    Gutter.ShowLineNumbers := true;
    Gutter.AutoSize := true;
    Gutter.LeadingZeros := false;
    Gutter.DigitCount := 3;
    Gutter.LineNumberStart := 0;
  end;

  // SynView erzeugen
  sedtViewCode := TSynEdit.Create(tabRun);
  with sedtViewCode do
  begin
    ReadOnly := true;
    Align := alClient;
    Parent := tabRun;

    WordWrap := true;

    Gutter.ShowLineNumbers := true;
    Gutter.AutoSize := true;
    Gutter.LeadingZeros := false;
    Gutter.DigitCount := 3;
    Gutter.LineNumberStart := 0;
  end;

  aLexer := TLexer.Create;
  aInterpreter := TInterpreter.Create(sedtSourceCode.Lines, aLexer);
end;

procedure TfrmMain.pgcModesChange(Sender: TObject);
begin
  // Code übernehmen
  sedtViewCode.Lines.Assign(sedtSourceCode.Lines);
  aInterpreter.Source := sedtViewCode.Lines;
end;
Läuft das Programm so, wie es hier steht, gibt es kein Problem.

Das Problem entsteht erst, wenn in der TInterpreter-Klasse ein Aufruf geschieht, der den SynEdit-Text verarbeiten soll:
Delphi-Quellcode:
procedure TfrmMain.RunRun1Execute(Sender: TObject);
begin
  // Initialisieren
  sedtViewCode.Lines.Assign(sedtSourceCode.Lines);
  aInterpreter.Source := sedtViewCode.Lines;
  pgcModes.ActivePage := tabRun;

  aInterpreter.OnGetData := self.GetDataInput;
  aInterpreter.OnFinished := self.ExecutionFinished;
  aInterpreter.Execute(lbxOutput.Items);
end;

procedure TAsmWorker.ParseLine(ALine: integer; var AOperation, AParam: string);
var
  iPos: integer;
begin
  FSource[ALine] := Trim(FSource[ALine]);
  // Erstmal alles als Operation ansehen
  AOperation := FSource[ALine];
  // Parameter-Anfang finden
  iPos := Pos(' ', AOperation[ALine]);
  if iPos > 0 then
  begin
    // Es sind Parameter vorhanden
    AParam := Copy(AOperation[ALine], iPos + 1, Length(AOperation) - iPos);
    Delete(AOperation, iPos, Length(AOperation) - iPos + 1);
  end else begin
    // Keine Parameter vorhanden
    AParam := '';
  end;
  // Nochmal alles trimmen
  AOperation := Trim(AOperation);
  AParam := Trim(AParam);
end;

function TInterpreter.Execute(AOutput: TStrings): Boolean;
{...}
begin
  // Initialisieren
  Result := true;
  EIP := 0;

  // Execution-Loop
  if (Source <> nil) and (EIP < Source.Count) then
  begin
    while ((cmdCommand <> nil) and (cmdCommand.Operation <> opStop))
      and (Result) and (EIP < Source.Count) and (not FTerminated) do
    begin
      // Zeile parsen
      ParseLine(EIP, sOperation, sParam);

      // Lexer ausführen
      cmdCommand := Lexer.CreateCommand(sOperation, sParam);
      if cmdCommand <> nil then
      begin
        // Operation ausführen
        case cmdCommand.Operation of
          { ... }
        end;
      end;

      Application.ProcessMessages;
      EIP := EIP + 1;
    end;
  end;
  { ... }
end;
Ich habe das soweit eingrenzen können, als dass das Problem in dem sedtSourceCode-SynEdit liegt. Außerdem liegt das Problem definitiv im Aufruf von aInterpreter.Execute.
Was mich allerdings wundert, da überall nur auf StringListen zugegriffen, wird, die nur den Text-Inhalt des SynEdits haben, jedoch eigentlich keinen Zeiger sein sollten (Assign weist ja den Inhalt zu und nicht den Zeiger auf den Inhalt aus einem anderen Feld).

So oder so bekomme ich eine EInvalidPointer-Exception in der SynTextDrawer.pas in TheTextDrawer.ReleaseETODist beim Beenden des Programmes.

Hat jemand eine Idee?

Chris
  Mit Zitat antworten Zitat