Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi SynEdit: EInvalidPointer beim Beenden (https://www.delphipraxis.net/88181-synedit-einvalidpointer-beim-beenden.html)

CalganX 11. Mär 2007 14:05


SynEdit: EInvalidPointer beim Beenden
 
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

Hawkeye219 11. Mär 2007 14:16

Re: SynEdit: EInvalidPointer beim Beenden
 
Hi Chris,

du definierst einen Setter, verwendest ihn aber gar nicht:

Delphi-Quellcode:
TWorker = class
[...]
  procedure SetSource(const ASource: TStrings);
published
  property Source: TStrings read FSource write FSource;
end;
Gruß Hawkeye

CalganX 11. Mär 2007 14:19

Re: SynEdit: EInvalidPointer beim Beenden
 
Nicht?
Delphi-Quellcode:
procedure TInterpreter.SetSource(const Value: TStrings);
begin
  inherited SetSource(Value);

  // Zurücksetzen
  EIP := 0;
  PrepareSource;
end;
Chris

mirage228 11. Mär 2007 14:28

Re: SynEdit: EInvalidPointer beim Beenden
 
Hi,

Ich glaube er meint das:

Dein Code
Delphi-Quellcode:
property Source: TStrings read FSource write FSource;
So so solltes sein ;)
Delphi-Quellcode:
property Source: TStrings read FSource write SetSource;
mfG
mirgae228

CalganX 11. Mär 2007 14:30

Re: SynEdit: EInvalidPointer beim Beenden
 
Hi David,
achso. Naja, und? Ist ja letztlich unerheblich, da es das Problem nicht löst. :zwinker:

Chris

CalganX 11. Mär 2007 15:27

Re: SynEdit: EInvalidPointer beim Beenden
 
Nachtrag: Habe jetzt, mit Davids Hilfe, herausgefunden, dass das Problem nur mit den Turbo-Versionen auftritt. Scheint also ein Problem zwischen SynEdit und Turbo Delphi zu sein.

Da ich auf die Schnelle den Bug jetzt nicht fixen kann, hab ich einfach folgendes gemacht im OnClose:
Delphi-Quellcode:
  // Aufräumen
  {!FIXME!}
  try {Needed for D2006/Turbo-Support}
    aInterpreter.Free;
    aLexer.Free;
    sedtViewCode.Free;
    sedtSourceCode.Free;
  except
    // Do nothing
  end;
  Application.Terminate;
Ist zwar alles andere als schön, aber Mittel zum Zweck.

Chris


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:29 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz