AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Destruktor löst Exception aus

Ein Thema von 3_of_8 · begonnen am 25. Apr 2006 · letzter Beitrag vom 25. Apr 2006
Antwort Antwort
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#1

Destruktor löst Exception aus

  Alt 25. Apr 2006, 19:13
Morgen.

Ich habe folgendes Problem: Jedesmal, wenn ich den Destruktor einer von mir erstellten Klasse aufrufe, bekomme ich eine EInvalidPointer. Ich könnte es ja noch verstehen, wenn der Destruktor von mir überschrieben wäre, aber ich benutze den vererbten Destruktor (meine Klasse ist von TGraphicControl abgeleitet.)

Quelltext habe ich mal gepostet:

(Der gleiche Fehler tritt manchmal auch im Konstruktor auf. Aber dort scheint er zufällig aufzutreten, im Destruktor tritt er immer auf.)

Delphi-Quellcode:
unit Module;

interface

{$R 'res\icons\icons.res'}
{$R 'res\images\images.res'}

uses Windows, Messages, Types, Classes, Controls, Graphics, Basic,
  Buttons, Forms, Dialogs, SysUtils, Port, IniFiles;

const
   WM_DESTROY_MODULE=Messages.WM_USER+42;

type
   TMessage=record
      Msg: Word;
  end;

  TModule=class;

    TModuleDestructionEvent=procedure(Sender: TObject;
     var DoDestroy: Boolean; Module: TModule) of object;

  TRectArray=array of TRect;

  TPortArray=array of TPort;

  TSpeedButtonArray=array of TSpeedButton;

  TTool=(tlMove=0, tlDelete=1, tlWire=2, tlModule=3);

  TModuleInfo=record
    Group, ID: Byte;
    Title: string;
  end;

  TWirePoint=record
    X, Y: Integer;
  end;

  TWire=record
    Nodes: array of TWirePoint;
    BitWidth: Cardinal;
    Sender, Recipient: TModule;
  end;

  TModule=class(TGraphicControl)
  protected
    FMovable: Boolean;
    FInitialX, FInitialY: Integer;
    FImage: TBitmap;
    FInputPorts, FOutputPorts: TPortArray;
      FActiveTool: TTool;
    FTitle: String;
    FGroup, FID: Cardinal;
    FInputPositions, FOutputPositions: TRectArray;
    procedure HandleMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure HandleMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure HandleMouseMove(Sender: TObject; Shift: TShiftState;
      X, Y: Integer);
  public
    constructor Create(AOwner: TComponent); override;
    class function GetTitle: String;
    procedure Compute; virtual; abstract;
    property Group: Cardinal read FGroup;
    property ID: Cardinal read FID;
  published
    property Movable: Boolean read FMovable write FMovable default True;
    property Image: TBitmap read FImage write FImage;
    property InputPorts: TPortArray read FInputPorts write FInputPorts;
    property OutputPorts: TPortArray read FOutputPorts write FOutputPorts;
    property ActiveTool: TTool read FActiveTool write FActiveTool;
  end;

  TAutoLoadingModule=class(TModule)
  public
    constructor Create(AOwner: TComponent); override;
    procedure Paint; override;
  end;

  TModuleClass=class of TModule;

procedure AddModuleButton(Module: TModuleClass; var ModuleButtons:
  TSpeedButtonArray; Parent: TWinControl; OnClick: TNotifyEvent;
  Indent: Integer=4; GroupIndex: Integer=1);

implementation

procedure AddModuleButton(Module: TModuleClass; var ModuleButtons:
  TSpeedButtonArray; Parent: TWinControl; OnClick: TNotifyEvent;
  Indent: Integer=4; GroupIndex: Integer=1);
var Button: TSpeedButton;
begin
  Button:=TSpeedButton.Create(Parent);
  Button.Parent:=Parent;
  Button.Glyph.LoadFromResourceName(HINSTANCE, Module.ClassName);
  Button.Width:=28;
  Button.Height:=28;
  Button.Left:=Indent+length(ModuleButtons)*32;
  Button.Top:=4;
  Button.Tag:=Integer(Module);
  Button.OnClick:=OnClick;
  Button.GroupIndex:=GroupIndex;
  Button.Hint:=Module.GetTitle;
  Button.ShowHint:=True;
  Button.Flat:=True;
  setlength(ModuleButtons, length(ModuleButtons)+1);
  ModuleButtons[high(ModuleButtons)]:=Button;
end;

constructor TModule.Create(AOwner: TComponent);
var ini: TIniFile;
      CN: String;
    I, n: Integer;
begin
  inherited Create(AOwner);
  CN:=ClassName;
  if csOpaque in ControlStyle then ControlStyle:=ControlStyle- [csOpaque];
  OnMouseDown:=HandleMouseDown;
  OnMouseUp:=HandleMouseUp;
  OnMouseMove:=HandleMouseMove;
  FMovable:=True;
   ini:=TIniFile.Create(ModuleConfigFile);
  try
   if ini.SectionExists(CN) then
  begin
  FGroup:=ini.ReadInteger(CN,'Group',0);
  FID:=ini.ReadInteger(CN,'ID',0);
   FTitle:=ini.ReadString(CN,'Title','');
  n:=ini.ReadInteger(CN,'InputPorts',0);
  setlength(FInputPorts,n);
  for I:=1 to n do
     FInputPorts[I]:=TPort.Create(Compute,1,Rect(
       ini.ReadInteger(CN,'Input'+inttostr(I)+'Left',0),
      ini.ReadInteger(CN,'Input'+inttostr(I)+'Top',0),
      ini.ReadInteger(CN,'Input'+inttostr(I)+'Right',0),
      ini.ReadInteger(CN,'Input'+inttostr(I)+'Bottom',0)));
  n:=ini.ReadInteger(CN,'OutputPorts',0);
  setlength(FOutputPorts,n);
  for I:=1 to n do
     FOutputPorts[I]:=TPort.Create(Compute,1,Rect(
       ini.ReadInteger(CN,'Output'+inttostr(I)+'Left',0),
      ini.ReadInteger(CN,'Output'+inttostr(I)+'Top',0),
      ini.ReadInteger(CN,'Output'+inttostr(I)+'Right',0),
      ini.ReadInteger(CN,'Output'+inttostr(I)+'Bottom',0)));
  end;
  finally
     ini.Free;
  end;
end;

class function TModule.GetTitle: String;
var ini: TIniFile;
begin
ini:=TIniFile.Create(ModuleConfigFile);
try
Result:=ini.ReadString(ClassName,'Title','');
finally
ini.free;
end;
end;

procedure TModule.HandleMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if FMovable and (ActiveTool=tlMove) then
  begin
    Screen.Cursor:=crSizeAll;
    FInitialX:=X;
    FInitialY:=Y;
  end;
end;

procedure TModule.HandleMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if FMovable then
  if (ActiveTool=tlMove) then
  begin
    Screen.Cursor:=crDefault;
  end;
  if (ActiveTool=tlDelete) then
  begin
      PostMessage(parent.Handle,WM_DESTROY_MODULE,Integer(Self),0);
  end;
 end;

procedure TModule.HandleMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  if (Shift=[ssLeft])and FMovable and (ActiveTool=tlMove) then
  begin
    Left:=(Left+X-FInitialX)div 8*8;
    Top:=(Top+Y-FInitialY)div 8*8;
  end;
end;

constructor TAutoLoadingModule.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FImage:=TBitmap.Create;
  FImage.LoadFromResourceName(HInstance, '_'+ClassName);
  Width:=FImage.Width;
  Height:=FImage.Height;
  Constraints.MinWidth:=FImage.Width;
  Constraints.MaxWidth:=FImage.Width;
  Constraints.MinHeight:=FImage.Height;
  Constraints.MaxHeight:=FImage.Height;
end;

procedure TAutoLoadingModule.Paint;
begin
  inherited Paint;
  Canvas.Brush.Style:=bsClear;
  Canvas.Pen.Style:=psClear;
  Canvas.BrushCopy(FImage.Canvas.ClipRect, FImage,
    FImage.Canvas.ClipRect, clFuchsia);
end;

end.
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#2

Re: Destruktor löst Exception aus

  Alt 25. Apr 2006, 19:37
Hallo,

die Variablen FInputPorts und FOutputPorts sind dynamische Arrays, deren Elements die Nummern 0..n-1 tragen.
Du benutzt aber die Elemente 1..n und überschreibst damit den Speicher hinter den Arrays:

Delphi-Quellcode:
for I:=1 to n do
   FInputPorts[I]:=TPort.Create(Compute,1,Rect(
     ini.ReadInteger(CN,'Input'+inttostr(I)+'Left',0),
     ini.ReadInteger(CN,'Input'+inttostr(I)+'Top',0),
     ini.ReadInteger(CN,'Input'+inttostr(I)+'Right',0),
     ini.ReadInteger(CN,'Input'+inttostr(I)+'Bottom',0)));
n:=ini.ReadInteger(CN,'OutputPorts',0);
setlength(FOutputPorts,n);
for I:=1 to n do
   FOutputPorts[I]:=TPort.Create(Compute,1,Rect(
     ini.ReadInteger(CN,'Output'+inttostr(I)+'Left',0),
    ini.ReadInteger(CN,'Output'+inttostr(I)+'Top',0),
    ini.ReadInteger(CN,'Output'+inttostr(I)+'Right',0),
    ini.ReadInteger(CN,'Output'+inttostr(I)+'Bottom',0)));
end;
Gruß Hawkeye
  Mit Zitat antworten Zitat
Thorben77

Registriert seit: 22. Okt 2004
359 Beiträge
 
#3

Re: Destruktor löst Exception aus

  Alt 25. Apr 2006, 19:45
Außerdem musste Du alle Klasseninstanzen, die Du im Konstruktor und anderswo erstellst, im Destruktor wieder freigeben; konkret meine ich die TPort-Instanzen in Deinem Port-Array, die Du hier erstellst :
Delphi-Quellcode:
  for I:=1 to n do
     FInputPorts[I]:=TPort.Create(Compute,1,Rect(
       ini.ReadInteger(CN,'Input'+inttostr(I)+'Left',0),
      ini.ReadInteger(CN,'Input'+inttostr(I)+'Top',0),
      ini.ReadInteger(CN,'Input'+inttostr(I)+'Right',0),
      ini.ReadInteger(CN,'Input'+inttostr(I)+'Bottom',0)));
  n:=ini.ReadInteger(CN,'OutputPorts',0);
  setlength(FOutputPorts,n);
  for I:=1 to n do
     FOutputPorts[I]:=TPort.Create(Compute,1,Rect(
       ini.ReadInteger(CN,'Output'+inttostr(I)+'Left',0),
      ini.ReadInteger(CN,'Output'+inttostr(I)+'Top',0),
      ini.ReadInteger(CN,'Output'+inttostr(I)+'Right',0),
      ini.ReadInteger(CN,'Output'+inttostr(I)+'Bottom',0)));
  end;
Edit: Und Du solltest, wie Hawkeye219 schon schreibt, die for-Schleife so schreiben:
for I := 0 to n - 1 do
  Mit Zitat antworten Zitat
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: Destruktor löst Exception aus

  Alt 25. Apr 2006, 19:54


Komischerweise funktioniert es manchmal und manchmal nicht.

Und was den Destruktor betrifft, so ist der atm mein Hauptproblem. Und die TPort Instanzen sind dann zwar unschön, weil "Speichermüll", aber trotzdem nicht für die InvalidPointer Exception verantwortlich, oder?

EDIT: Wie war das mit dem Wald und den Bäumen? Naja egal, auf jeden Fall funktioniert es jetzt. Fragt mich nicht warum, aber es geht. Komischerweise konnte ich die Exceptions nicht mit Haltepunkten lokalisieren. Die Exception ist immer nach der letzten Anweisung im Konstruktor aufgetreten, bzw. an einer unbekannten Stelle im Destruktor.
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
Angel4585

Registriert seit: 4. Okt 2005
Ort: i.d.N.v. Freiburg im Breisgau
2.199 Beiträge
 
Delphi 2010 Professional
 
#5

Re: Destruktor löst Exception aus

  Alt 25. Apr 2006, 20:03
Zitat von 3_of_8:
Komischerweise konnte ich die Exceptions nicht mit Haltepunkten lokalisieren. Die
Exception ist immer nach der letzten Anweisung im Konstruktor aufgetreten, bzw. an einer unbekannten Stelle im Destruktor.
Das hatte ich auch mal.. dann hab ich mir angewöhnt eine Application.OnException zuzuweisen und dort ALLE Exceptions abzufangen die ich nicht mit nem try except Block bekomme.
Martin Weber
Ich bin ein Rüsselmops
  Mit Zitat antworten Zitat
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#6

Re: Destruktor löst Exception aus

  Alt 25. Apr 2006, 20:04
Das ist aber nicht gerade guter Stil...
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
Thorben77

Registriert seit: 22. Okt 2004
359 Beiträge
 
#7

Re: Destruktor löst Exception aus

  Alt 25. Apr 2006, 20:12
Zitat von 3_of_8:
Und was den Destruktor betrifft, so ist der atm mein Hauptproblem. Und die TPort-Instanzen sind dann zwar unschön, weil "Speichermüll", aber trotzdem nicht für die InvalidPointer-Exception verantwortlich, oder?
Selbst dann soltest Du sie freigeben:
Delphi-Quellcode:
TModule = class(TGraphicControl)
  public
    destructor Destroy; override;
  end;

...

destructor TModule.Destroy;
var
  I: Integer;
begin
  for I := Length(FInputPorts) - 1 downto 0 do
    FInputPorts[I].Free;
  for I := Length(FOutputPorts) - 1 downto 0 do
    FOutputPorts[I].Free;
  inherited Destroy;
end;
Das sollte Dich wohl nicht überfordern .


Zitat von 3_of_8:
Das ist aber nicht gerade guter Stil...
*zustimm*
  Mit Zitat antworten Zitat
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#8

Re: Destruktor löst Exception aus

  Alt 25. Apr 2006, 22:09
Jaja, habe ich schon gemacht. Allerdings kommt "Speicherlecks entfernen" für mich erst nach "Das ganze zum Laufen bringen."

Ich hab das schon gemacht, direkt nachdem das Programm funktioniert hat. Jetzt gehts auf zur Verdrahtung. Das wird kompliziert.
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:39 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