Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Accessviolation in Klassen-Prozedur (https://www.delphipraxis.net/49998-accessviolation-klassen-prozedur.html)

knusprig 19. Jul 2005 14:42


Accessviolation in Klassen-Prozedur
 
Hi,

ich hab ein kleines Problemchen mit meinem Programm. Es geht um folgenden Quellcode.

Delphi-Quellcode:
type TGraph = class(TObject)
  //Felder
  xlength : integer;
  ylength : integer;
  center : TPoint;
  //Methoden
  procedure DrawAxes(Canvas: TCanvas; center: TPoint; xlength, ylength: integer);
  procedure DrawHorzMarkers(Canvas: TCanvas; Left: TPoint; len: Integer);
  procedure DrawVerMarkers(Canvas: TCanvas; Top: TPoint; len: Integer);
end;

//*****************************************************************************
//Klassendefinition von TSchieber
//*****************************************************************************
type TSchieber = class(TGraph)
  //Felder
  l : real;                //Vom Benutzer angegeben
  r : real;                //Vom Benutzer angegeben
  a : real;                //Strecke von 0 bis Berührung auf x
  b : real;                //Strecke von 0 bis Berührung auf y
  px : real;               //X-Wert des Punktes P
  py : real;               //Y-Wert des Punktes P
  rad : real;              //Radius des Kreises um den Punkt P
  richtung : boolean;      //Richtung des Doppelschiebers
  //Methoden
  procedure DrawLine(Canvas: TCanvas; a: integer);
end;


implementation

.........
.........

procedure TSchieber.DrawLine(Canvas: TCanvas; a: integer);
begin
  //Berechnung der Strecken
  l := strtoint(wertsetzen.valueset.Edit_L.text);
  r := strtoint(wertsetzen.valueset.Edit_R.text);
  b := (sqrt(sqr(l)-sqr(a)));

  //Berechnung der Koordinaten
  canvas.MoveTo(center.x, center.y + trunc(b));
  canvas.LineTo(center.x + a, center.y);

end;

In der Zeile, in der l den Wert aus Edit_L zugewiesen bekommt, erhalte ich beim compilen eine Access Violation. Kann mir jemand sagen warum und was ich dagegen machen kann?

bttb930 19. Jul 2005 14:47

Re: Accessviolation in Klassen-Prozedur
 
wahrscheinlich ist wertsetzen.valueset.Edit_L oder wertsetzen.valueset oder wertsetzen nil bzw. verweist ins nirvana

Khabarakh 19. Jul 2005 14:51

Re: Accessviolation in Klassen-Prozedur
 
Es ist nicht wirklich im Sinne von OOP, dass sich eine Klasse selbstständig Parameter aus einem Formular (erst recht nicht aus der globalen Variable) heraussucht. Du solltest l und b lieber als Paramater übergeben oder Properties anlegen.

knusprig 19. Jul 2005 14:52

Re: Accessviolation in Klassen-Prozedur
 
Nein, eigentlich nicht. Das befindet sich in einem anderen Formular. Also da kann es normalerweise nicht dran liegen.

Das mit den properties hab ich mir auch schon gedacht. Hab ich auch probiert aber nicht hinbekommen. Kann mir jemand sagen wie ich das genau schreiben muss. Bin noch ein Delphi-Neuling :)

barf00s 19. Jul 2005 14:53

Re: Accessviolation in Klassen-Prozedur
 
1. beim compilen bekommst nen EAccessViolation? das halt ich fürn gerücht :) eher bei der ausführung deines codes
2. hat dir mammi nich erklärt in klassen ein/ausgabe methoden von den reinen datenverarbeitenden methoden zu trennen?
3. klassenprozedur wäre was anderes :) "class procedure" - war etwas verwirrt beim öffnen dieses dingsens hier
4. wie man objekt orientiert programmiert - http://www.delphibasics.co.uk/Article.asp?Name=OO - das solltest dir eventuell mal zu gemüte führen
5.

Delphi-Quellcode:
type
  TGraph = class{(TObject)}
  private
    FXLength: integer;
    FYLength: integer;
    FCenter: TPoint;
    FCanvas: TCanvas;
    procedure SetXLength(const Value: integer);
    procedure SetYLength(const Value: integer);
    procedure SetCenter(const Value: TPoint);
  public
    constructor Create(ACanvas: TCanvas);
    procedure DrawAxes;
    procedure DrawHorzMarkers(Left: TPoint; Len: integer);
    procedure DrawVertMarkers(Top: TPoint; Len: integer);
    property XLength: integer read FXLength write SetXLength;
    property yLength: integer read FYLength write SetYLength;
    property Center: TPoint read FPoint write SetPoint;
    property Canvas: FCanvas write FCanvas;
  end;

implementation

constructor TGraph.Create(ACanvas: TCanvas);
begin
  inherited Create;
  FCanvas := ACanvas;
end;

procedure TGraph.SetXLength;
begin
  if FXLength <> Value then
    FXLength := Value;
end;

procedure TGraph.SetYLength;
begin
  if FYLength <> Value then
    FYLength := Value;
end;

procedure TGraph.SetCenter;
begin
  if (FCenter.X <> Value.X) or (FCenter.Y <> Value.Y) then
    FCenter := Value;
end;

procedure TGraph.DrawAxes;
begin
  if not Assigned(FCanvas) then
    Exit;
  with FCanvas do begin
    // hier der malkrams
  end;
end;

// bei den andern Draw* isses dann dasselbe, und du greifst auf FXLength, FYLength & FCenter zurück -

BlackJack 19. Jul 2005 14:53

Re: Accessviolation in Klassen-Prozedur
 
zeig mal die deklaration von diesem "wertsetzen" bzw. auch wo die variable steht.

knusprig 19. Jul 2005 15:00

Re: Accessviolation in Klassen-Prozedur
 
Also erstmal sorry für evt. falsche Begriffe oder ähnliches :oops:
Hab sämtliches Delphi-Wissen aus einem Buch, und es ist jetzt schon ein bißchen her dass ich das gelesen hab.

Also in wertsetzen is bis jetzt noch nichts weiter drin als zwei Eingabefelder für die Werte l und r. Mehr ist da nicht.

Ultimator 19. Jul 2005 15:02

Re: Accessviolation in Klassen-Prozedur
 
Hmmm, ich weiß nicht wieso du das machst, aber die Variablen in deiner TGraph-Klasse sind real.
Dann weist du ihnen über StrToInt einen Wert aus einem Edit zu.
Dieses Edit solltest du vorher auf gültige Integerwerte überprüfen.
Und was mich stutzig macht: Du deklarierst die Variablen als real aber weist ihnen bloß Inter-Werte zu: Speicherverschwendung ;)

Außerdem ist der Typ real nur noch aus Kompatibilitätsgründen da, verwende besser single, double oder extended, die sind für den Prozessor schneller verarbeitbar ;)


Mir fällt auf: Ein Delphiprogrammierer aus Coburg *freu* :)

knusprig 19. Jul 2005 15:15

Re: Accessviolation in Klassen-Prozedur
 
Hm, da hast du recht. Hab das ganze schon zu real geändert. Werde jetzt mal versuchen, die Werte übergeben zu lassen.

Ui, noch ein Coburger :)

BlackJack 19. Jul 2005 15:23

Re: Accessviolation in Klassen-Prozedur
 
Zitat:

Zitat von barf00s
Delphi-Quellcode:
procedure TGraph.SetXLength;
begin
  if FXLength <> Value then
    FXLength := Value;
end;

was bringt das denn? wenn du den wert direkt setzt ohne überprüfung, ändert sich auch nichts, und du sparst dir den vergleich. und dannn kannst du dir gleich die ganze procedure und (meiner meinung nach) auch die property sparen und direkt die variable benutzen - oder hat eine property a la
Delphi-Quellcode:
fi: Integer;
property i: integer read fi write fi;
irgend einen sinn?

edit:
Zitat:

Zitat von Ultimator
Außerdem ist der Typ real nur noch aus Kompatibilitätsgründen da, verwende besser single, double oder extended, die sind für den Prozessor schneller verarbeitbar Wink

stimmt nicht so ganz - standardmäßig entspricht ein Real einem Double, d.h. du kannst ruhig Real verwenden, damit kommt die FPU von sich aus schon klar. du meisnt wahrscheinlich den alten TurboPascal-Real mit 48Bit und einem Borland-eigenen format, mit dem die FPU so nicht klarkommt und der erst umgewandelt werden muss (was natürlich zeit kostet). den gibt es unter delphi (aus welchen grunden auch immer) noch immer, er heisst Real48.

p.s.: es gibt auch einen compilerschalter, der bewirkt, dass ein Real einem Real48 entspricht.

barf00s 19. Jul 2005 15:26

Re: Accessviolation in Klassen-Prozedur
 
es kann ja sein das er in einer späteren version seines programmes IRGENDeinen vergleich braucht, um fehler zu vermeiden - und - ich habe im implementation teil einfach die parameter weggelassen weil ich zu faul zum tippsen war -

[edit]
Zitat:

stimmt nicht so ganz - standardmäßig entspricht ein Real einem Double, d.h. du kannst ruhig Real verwenden, damit kommt die FPU von sich aus schon klar. du meisnt wahrscheinlich den alten TurboPascal-Real mit 48Bit und einem Borland-eigenen format, mit dem die FPU so nicht klarkommt und der erst umgewandelt werden muss (was natürlich zeit kostet). den gibt es unter delphi (aus welchen grunden auch immer) noch immer, er heisst Real48.
real entspricht nicht einem double, sondern einem single, und real ist tatsächlich aus kompatiblitätsgrundn noch in delphi implementiert/vorhanden

[/edit

BlackJack 19. Jul 2005 15:31

Re: Accessviolation in Klassen-Prozedur
 
Zitat:

Zitat von barf00s
und - ich habe im implementation teil einfach die parameter weggelassen weil ich zu faul zum tippsen war -

das hatte ich schon erkannt ;)

aber so eine property wie ich sie gepostet habe (die also per read und write direkt mit einer variablen verbunden ist) macht doch aber tatsächlich keinen sinn, oder?

Zitat:

Zitat von barf00s
real entspricht nicht einem double, sondern einem single, und real ist tatsächlich aus kompatiblitätsgrundn noch in delphi implementiert/vorhanden

oha, man lehrnt nie aus, ich dachte immer ein Real wäre ein double. naja aber ich sehe trotzdem keinen grund nicht weiter mit Real zu arbeiten (obwohl ich auch lieber single oder double benutze).

knusprig 19. Jul 2005 17:24

Re: Accessviolation in Klassen-Prozedur
 
Also ich übergeb jetzt die Werte in die procedure. Die sieht jetzt so aus:

Delphi-Quellcode:
procedure TSchieber.DrawLine(Canvas: TCanvas; a,l,r: double);
begin
  //Berechnung der Strecken
  b := sqrt(sqr(l)-sqr(a));

  //Berechnung der Koordinaten
  canvas.MoveTo(center.x, center.y + b);
  canvas.LineTo(center.x + a, center.y);

end;
Jetzt hab ich zum einen noch das Problem dass die Werte a und b Integer sein müssen. Sollte ich vielleich runden?!? Aber nun hab ich das Problem "Ungültige Gleitkommaoperation in der Zeile wo b berechnet wird....
:(

Robert_G 19. Jul 2005 17:45

Re: Accessviolation in Klassen-Prozedur
 
Zitat:

Zitat von BlackJack
aber so eine property wie ich sie gepostet habe (die also per read und write direkt mit einer variablen verbunden ist) macht doch aber tatsächlich keinen sinn, oder?

Doch, sie abstrahiert die Felder der Klasse und gibt dir somit die Möglichkeit später zum Bleistift einen setter dazwischenzuschieben, der meinetwegen einen Event auslösen oder auch andere Felder invalidieren kann. ;)
btw: Selbst eine Property, die per "read fFeld" deklariert ist, sollte im Code auch nur als Property und nicht als Feld verwendet werden. Es sollte dadurch keine Performanceprobleme geben und du hast wieder die Verwendung soweit vom Feld getrennt, das spätere Änderungen in einem Getter möglich sind...
Ist es eine readonly Property muss man natürlich das Feld zum Schreiben nehmen. ;)

Außerdem könnte man die Property in den published Teil schieben, wenn man das Delphi streaming system bzw. RTTI verwenden will. ;)

kurz gesagt: Barfoos hat das schon ganz richtig gemacht. Und es sieht hübscher aus... :mrgreen:

marabu 19. Jul 2005 17:57

Re: Accessviolation in Klassen-Prozedur
 
Zitat:

Zitat von knusprig
Aber nun hab ich das Problem "Ungültige Gleitkommaoperation in der Zeile wo b berechnet wird.

Sqrt() ist nur für nicht-negative Werte definiert - wo ist deine Prüfabfrage?

Grüße vom marabu

PS: Berechnung einer Strecke? Sqrt(Abs(...))

knusprig 19. Jul 2005 18:02

Re: Accessviolation in Klassen-Prozedur
 
Zitat:

Zitat von marabu
Zitat:

Zitat von knusprig
Aber nun hab ich das Problem "Ungültige Gleitkommaoperation in der Zeile wo b berechnet wird.

PS: Berechnung einer Strecke? Sqrt(Abs(...))

Vielen Dank. Damit erscheint schonmal keine Fehlermeldung mehr :) Wieder ein Schritt weiter. Vielleicht bekomm ich das ja doch noch gebacken :)

BlackJack 19. Jul 2005 19:01

Re: Accessviolation in Klassen-Prozedur
 
Zitat:

Zitat von Robert_G
Zitat:

Zitat von BlackJack
aber so eine property wie ich sie gepostet habe (die also per read und write direkt mit einer variablen verbunden ist) macht doch aber tatsächlich keinen sinn, oder?

Doch, sie abstrahiert die Felder der Klasse und gibt dir somit die Möglichkeit später zum Bleistift einen setter dazwischenzuschieben, der meinetwegen einen Event auslösen oder auch andere Felder invalidieren kann. ;)

ok, an abgeleitete kalssen habe ich nicht gedacht, da macht das natürlich sinn.

Zitat:

Zitat von Robert_G
btw: Selbst eine Property, die per "read fFeld" deklariert ist, sollte im Code auch nur als Property und nicht als Feld verwendet werden. Es sollte dadurch keine Performanceprobleme geben[...]

erzeugt delphi da echt keinen overhead und handelt eine "read fFeld write fFeld"-Property dann intern (also nachher in der binary) wie einen direkten zugriff auf die vairable fFeld? dann sollte ich mir das mal überlegen tatsächlich immer mit propertys zu arbeiten, mich hat da immer der (vermeintliche?) overhead und die damit zusammenhängenden geschwindigkeitsverluste abgeschreckt, da ich oft relativ zeitkritische programme schreibe.

p.s.: [OT] ist das normal dass beim Firefox im eingabefeld (also da wo ich jetzt gerade tippe) der cursor so "laggt"? das nervt allmählich wie sau! :kotz:


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:44 Uhr.

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