Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Hilfe beim Beheben einer Access Violation (https://www.delphipraxis.net/126626-hilfe-beim-beheben-einer-access-violation.html)

Romi 29. Dez 2008 20:27


Hilfe beim Beheben einer Access Violation
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,

in diesem Thread habe ich ein Programm namens JewelCrack vorgestellt, das noch einen Fehler enthält: Es treten scheinbar zufällig Access Violations auf.

Ich habe diese schon mehrfach im Debugger abgefangen. Sie treten auf, wenn ich auf einen Stein zugreife.

Zum Aufbau des Programms (Sourcecode hängt auch unten an):
Ich habe einen Array[1..400] of tStein. Dieser wird am Anfang mit Steinen bis an den Rand gefüllt und dann werden Einzelne dieser Steine immer wieder zerstört. Ich gehe sehr oft diesen Array durch und greife dabei dann auf bestimmte Steine zu (natürlich nachdem ich geprüft habe, dass diese nicht nil sind und dass diese nicht "deaded" sind (das ist die Andorra2D-Methode (der Grafikengine, die ich benutzte), Sprites zu töten). Und genau bei diesen Zugriffen passiert es. Das komische ist, dass es nicht immer passiert. Man kann gerne mal fünf Spiele spielen, ohne das etwas passiert, und bei sechsten schmeisst er dann mit Fehlern um sich.

Noch ein Kommentar zum Sourcecode:
Er ist technisch gesehen sicherlich nicht sonderlich schön. Aber ich habe ihn ein wenig Kommentiert und strukturiert ist er auch, er sollte eigentlich relativ leicht zu lesen sein. Verbesserungsvorschläge und Unschönheiten in meiner Arbeit nehme ich allerdings gerne entgegen, man will ja dazulernen ;)
Erstellt wurde er mit Delphi 7, später zu Delphi 2009 konvertiert. Die Projektdatei ist also für D2009.

Es ist mir eigentlich relativ egal, was ihr mit dem Sourcecode macht. Nur wenn ihr ihn modifizieren wollt, dann lasst doch bitte meinen Namen dabei stehen.

Danke schonmal,
Roman

EDIT: Hier bekommt ihr Andorra2D her: http://downloads.sourceforge.net/and...se_mirror=osdn

hoika 29. Dez 2008 20:46

Re: Hilfe beim Beheben einer Access Violation
 
Hallo,

AdDraws not found.

Ist wohl diese Andorra ?

Warum hängt das nicht mit dan ?
*faul*
Ausserdem gibt es je verschieden Versions-Stände.



Heiko

Romi 29. Dez 2008 20:47

Re: Hilfe beim Beheben einer Access Violation
 
Zitat:

Zitat von hoika
Hallo,

AdDraws not found.

Ist wohl diese Andorra ?

Warum hängt das nicht mit dan ?
*faul*
Ausserdem gibt es je verschieden Versions-Stände.



Heiko

Achso, natürlich. Andorra2D gibts hier: http://downloads.sourceforge.net/and...se_mirror=osdn

hoika 29. Dez 2008 20:56

Re: Hilfe beim Beheben einer Access Violation
 
Hallo,

nunja ;(
klappt ja erst ab D7 (habe hier D6).

Aber

Das hier so komisch aus.
Delphi-Quellcode:
  for i := 1 to 400 do
    if (Steine[i] <> nil) AND not (Steine[i].Deaded) then Steine[i].dead;

  XXX

      Steine[arr] := tStein.Create(AdSpriteEngine);
      Steine[arr].einrichten(offsetX, offsetY, random(5));
Bist dui dir sicher, dass die Stein auch wirklich als Klasse (Objekt) gelöscht werden.
Scheibe mal einen destructor für TStein und setze mal nen BreakPoint.

Der Destructor muss ja bei .dead aufgerufen werden.

Ausserdem würde ich mal mit memcheck oder FastMM4 prüfen, ob irgendwelche Speicherlecks drin sind.


Heiko

Romi 29. Dez 2008 21:10

Re: Hilfe beim Beheben einer Access Violation
 
Danke für deine Antwort.

Zitat:

Zitat von hoika
Bist dui dir sicher, dass die Stein auch wirklich als Klasse (Objekt) gelöscht werden.
Scheibe mal einen destructor für TStein und setze mal nen BreakPoint.

Die Klasse tStein erbt ja von TImageSpriteEx. Diese erbt wiederrum von ein paar anderen Klassen, aber ganz unten haben diese auch einen Destructor, der aufgerufen wird, sobald das Sprite "dead" ist.

Zitat:

Zitat von hoika
Ausserdem würde ich mal mit memcheck oder FastMM4 prüfen, ob irgendwelche Speicherlecks drin sind.

Mh, hab ich keine Ahnung von. Aber das werde ich mir mal angucken.

hoika 29. Dez 2008 21:19

Re: Hilfe beim Beheben einer Access Violation
 
Hallo,

memcheck finde ich einfacher


in der dpr als erste unit mit

uses
MemCheck,

Memcheck einbinden
(http://v.mahon.free.fr/pro/freeware/memcheck/)

und als 1. Befehl nach dem Begin

begin
MemChk;

Damit wird NACH dem Programm laufen (also nach dem Beenden) Speicherlecks angezeigt.


Heiko

Romi 29. Dez 2008 21:28

Re: Hilfe beim Beheben einer Access Violation
 
Also, mit memcheck crasht das Ding sofort am Start. Warscheinlich inkompatibel zu D2009?

lbccaleb 29. Dez 2008 21:40

Re: Hilfe beim Beheben einer Access Violation
 
Hey,
probiers mal mit FastMM!

hoika 29. Dez 2008 22:59

Re: Hilfe beim Beheben einer Access Violation
 
Hallo,

< Also, mit memcheck crasht das Ding sofort am Start. Warscheinlich inkompatibel zu D2009? >
hm ?

Mal nen breakpoint in die dpr gesetet ?


Heiko

rollstuhlfahrer 30. Dez 2008 00:04

Re: Hilfe beim Beheben einer Access Violation
 
HI,

keine Ahnung, ob das weiterhilft, aber nutze mal zum Zerstören FreeAndNil. So hast du auf jeden Fall ein NULL-Objekt. Und auch bei Exceptions beim Free - mal den Wert mit nil überschreiben (auch wenn dann ein Speicherleck entsteht). Ansonsten, wie gesagt: Schnelle boolische Auswertung mit {$B+} anschalten.

Bernhard

Romi 30. Dez 2008 00:46

Re: Hilfe beim Beheben einer Access Violation
 
Zitat:

Zitat von rollstuhlfahrer
keine Ahnung, ob das weiterhilft, aber nutze mal zum Zerstören FreeAndNil.

Wer oder was ist denn FreeAndNil? ;)

Zitat:

Zitat von rollstuhlfahrer
Schnelle boolische Auswertung mit {$B+} anschalten.

Was macht das genau? Ist das das selbe wie in den Projektoptionen "Vollständige Boolesche Auswertung"? Das stand auf False.

hoika 30. Dez 2008 07:22

Re: Hilfe beim Beheben einer Access Violation
 
Hallo,

nein, damit erreicht du das Gegenteil.
Zur Frage, was das ist,
gibt es doch die schöne Hilfe ?

Akademisches Bsp:

Delphi-Quellcode:
function Foo: Integer;
begin
  Result:= 1;
end;

{$B+}
a:= 0;
if (a=0) or (b=Foo)
Es wird nur der 1. Teil ausgewertet,
da das Endergebnis ja schon True ist

Foo als Funktion wird überhaupt nicht angesprungen.

Das kann gut sein, oder nicht,
je nachdem, ob der Programmierer in Foo etwas macht,
was immer gemacht werden soll, oder nicht.

Ist immer lustig, solche Sachen zu suchen und zu finden.


Heiko

Romi 30. Dez 2008 12:53

Re: Hilfe beim Beheben einer Access Violation
 
Zitat:

Zitat von hoika
Zur Frage, was das ist,
gibt es doch die schöne Hilfe ?

Oh ja, die kann ich leider nicht öffnen. Der Microsoft Document Explorer sei nicht installiert, ist er aber.

Zitat:

Zitat von hoika
Ist immer lustig, solche Sachen zu suchen und zu finden.

Ich teste gerade noch, aber ich glaube das wars.

hoika 30. Dez 2008 13:59

Re: Hilfe beim Beheben einer Access Violation
 
Hallo,

zu deinem Hilfe-Problem.

1


Heiko

rollstuhlfahrer 30. Dez 2008 14:10

Re: Hilfe beim Beheben einer Access Violation
 
HI

FreeAndNil ist eine Delphi-Prozedur aus der Sysutils-Unit.
Der interne Aufbau sieht wie folgt aus:
Delphi-Quellcode:
procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;
Zuerst wird Temp das Objekt (die Komponente oder sonst was) zugewiesen. Dann wird der VAR-Parameter auf nil gesetzt. -> Fazit: er ist eindeutig nil. Danach wrd noch das Objekt aus dem Speicher geräumt. Achtung: Da .Free von TObject aufgerufen wird, darf diese Prozedur nirgendwo überschrieben werden, was bei manchen Programmierern manchmal vorkommt. Zerstört wird in .Destroy.

Bernhard

mkinzler 30. Dez 2008 14:12

Re: Hilfe beim Beheben einer Access Violation
 
Zitat:

Da .Free von TObject aufgerufen wird, darf diese Prozedur nirgendwo überschrieben werden,
Überschrieben werden schon, man muss in diesem Fall nur sicherstellen, das die geerbte Variante am Schluss aufgerufen wird

Romi 30. Dez 2008 14:25

Re: Hilfe beim Beheben einer Access Violation
 
Naja, {B+} hat doch nicht geholfen. Schade, ich hatte 9 Spiele am Stück, das sah so gut aus :|

Zitat:

Zuerst wird Temp das Objekt (die Komponente oder sonst was) zugewiesen. Dann wird der VAR-Parameter auf nil gesetzt. -> Fazit: er ist eindeutig nil. Danach wrd noch das Objekt aus dem Speicher geräumt. Achtung: Da .Free von TObject aufgerufen wird, darf diese Prozedur nirgendwo überschrieben werden, was bei manchen Programmierern manchmal vorkommt. Zerstört wird in .Destroy.
Das klingt interessant. Du sagtest, es liegt in der SysUtils Unit, wie erweitere ich denn meine Klasse um diese Procedure?

Romi 2. Jan 2009 20:00

Re: Hilfe beim Beheben einer Access Violation
 
Zitat:

Zitat von Romi
Das klingt interessant. Du sagtest, es liegt in der SysUtils Unit, wie erweitere ich denn meine Klasse um diese Procedure?

*bump*
Vllt. noch jemand eine Ahnung?

mkinzler 2. Jan 2009 20:06

Re: Hilfe beim Beheben einer Access Violation
 
Nein Free ist eine Methode der Basis-Klasse TObject, von welcher alle Klassen direkt oder indirekt abgeleitet sind. Überschreibt man diese Methode sollte man am ende die geerbete Aufrufen:

Delphi-Quellcode:
procedure TMeineKlasse.Free();
begin
    ...
    inherited;
end;

Romi 2. Jan 2009 20:11

Re: Hilfe beim Beheben einer Access Violation
 
Zitat:

Zitat von mkinzler
Nein Free ist eine Methode der Basis-Klasse TObject, von welcher alle Klassen direkt oder indirekt abgeleitet sind. Überschreibt man diese Methode sollte man am ende die geerbete Aufrufen:

Delphi-Quellcode:
procedure TMeineKlasse.Free();
begin
    ...
    inherited;
end;

Danke für deine Antwort, aber es ging um FreeAndNil ;)

EDIT: Habs schon gefunden. Hatte mich bloß verlesen. Das löst das Problem mit der Acces Violation! Danke!

QuickAndDirty 2. Jan 2009 20:42

Re: Hilfe beim Beheben einer Access Violation
 
kannst du den stack inhalt sehen wenn die AV kommt?


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:30 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