Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Zugriffsverletzung bei Adresse 00000000 bei TImage (https://www.delphipraxis.net/127762-zugriffsverletzung-bei-adresse-00000000-bei-timage.html)

SuperSeb 18. Jan 2009 17:52


Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Hallo,

ich brauche mal wieder eure Hilfe.

Ich habe hier eine hübsche Zugriffsverletzung bei Adresse 00000000 'Lesen von Adresse 00000000' wenn ich im Code einer Klasse auf ein klasseneigenes TImage-Objekt zugreifen möchte. Also so ungefähr:

Delphi-Quellcode:
TKlasse = class
private
  Bild: TImage;
public
  procedure MachWas;
end;

//...

procedure TKlasse.MachWas;
begin
  //...
  Bild.Left := 20; //Hier rührt der Fehler her
  //...
end;
Normalerweise würde man sagen "Ganz klar, kein Objekt instanziert", aber:

Delphi-Quellcode:
constructor TKlasse.Create(AOwner: TComponent);
begin
  //...
  Bild := TImage.Create;
  //...
end;
Jetzt kommt's aber noch doller:

Wenn ich genau das gleiche, was ich mit diesem TImage-Objekt mache, mit einem anderen - nennen wir es Bild2 - mache, dann kommt kein Fehler. Und mit genau das gleiche meine ich ALLES gleich machen, d.h. cocy & paste bei allen Sachen für Bild im Code und auf Bild2 geändert.

Jetzt weis ich nicht mehr, wo ich noch nach dem Fehler suchen soll... Wenn ich die Stelle oben auskommentiere, gibts keinen Fehler mehr. Umbenennen des ersten TImage-Objekts auf irgendwas anderes bringt auch nix.

Ach ja - vllt. ist das noch wichtig: Die Fehlermeldung erscheint, wenn man die Form schließt und dann zeigt Delphi das CPU-Fenster...

Vielleicht könnt ihr mir ja einen Tipp geben, wo ich da mal ansetzen könnte zu suchen, da ich leider nicht den ganzen Code posten kann...

Gruß und Danke im Voraus

Seb

mkinzler 18. Jan 2009 17:53

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Existiert den eine Instanz von TKlasse?

3_of_8 18. Jan 2009 17:55

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Wenn du irgendwo eine AV bei Zugriff auf $00000000 erhältst, ist das meißstens ein Zugriff auf einen Pointer, der nil ist, bzw. auf einen Klassenzeiger, der nil ist, in diesem Fall ist dieser Pointer, der nil ist, wahrscheinlich self, du hast also vergessen, die Klasse zu erzeugen.

SuperSeb 18. Jan 2009 17:56

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Darf ich zitieren:

Zitat:

Normalerweise würde man sagen "Ganz klar, kein Objekt instanziert", aber:

Delphi-Quellcode:
constructor TKlasse.Create(AOwner: TComponent);
begin
  //...
  Bild := TImage.Create;
  //...
end;

Also: Ja, es existiert eine.

DeddyH 18. Jan 2009 18:00

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Hast Du evtl. 2 mal
Delphi-Quellcode:
Bild.Free;
im Source Deiner Klasse?

mkinzler 18. Jan 2009 18:01

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Hier sihet man nur, das eine Instanz für den Member Bild erzeugt wird. nicht aber für die Klasse TKlasse.

3_of_8 18. Jan 2009 18:02

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Nicht ob das Bild instantiiert ist, ob deine TKlasse instantiiert ist.

SuperSeb 18. Jan 2009 18:03

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
nein, nur einmal im destructor.

Das Seltsame ist ja auch, dass der Code theoretisch funktionieren müsste, bei dem einen auch praktisch funzt aber bei einem auch wieder nicht!

:coder2:

Edit: Ja, ist sie. Kann ich garantieren. Denn sonst würde der Rest auch nicht laufen (is n bisssschen größer die Klasse als nur das oben) und ich weis auch, dass ichs selbst eingebaut hab.

Kurz gesagt: Ja, bin zu 100% sicher.

DeddyH 18. Jan 2009 18:08

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Du hast aber TImage nicht neu deklariert? Ansonsten stimmt der Aufruf dessen Konstruktors nicht, da hier ein Parameter vom Typ TObject TComponent erwartet wird.

[edit] Parametertyp korrigiert [/edit]

3_of_8 18. Jan 2009 18:08

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Geh mal mit Breakpoint bis an die Stelle, wo der Fehler auftritt, und prüfe mit dem Evaluator den Wert von Self und von deinem Bild.

SuperSeb 18. Jan 2009 18:12

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
@DeddyH: O, stimmt. Tut mir Leid, hab oben das falsch geschrieben. Ist natürlich im Original-Code richtig mit Parameter.

@3_of_8: Bin dran...

himitsu 18. Jan 2009 18:15

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
muß man TImage nicht beim .Create einen Owner übergeben?
Zitat:

Zitat von SuperSeb
@DeddyH: O, stimmt. Tut mir Leid, hab oben das falsch geschrieben. Ist natürlich im Original-Code richtig mit Parameter.

und welches Objekt hast du da als Owner übergeben?

SuperSeb 18. Jan 2009 18:26

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
@3_of_8: Also, bin jetzt Zeile für Zeile durchgesprungen - läuft ohne Probleme. Der Fehler tritt erst auf, wenn man die Form schließt.

@himitsu: Also den AOwner habe ich durchgeschleift, d.h. das ist der des Klassen-Konstructors. Wahrscheinlich liegt hier der Hase im Pfeffer. Beim Erzeugen eines Objekts hatte ich dem Constructor schon mal Application mitgegeben, dann auch mal den eigenen Objektnamen. Es machte bisher keinen Unterschied und funktionierte Einwandfrei - habe auch schon gegooglet, aber so richtig schlau geworden, wo der Unterschied liegt, bin ich nicht.

Vielleicht sollte ich noch dazu sagen (jetzt werde ich wahrscheinlich gesteinigt), dass ich das Objekt unter initialization instanziere, denn wenn ich das erst bei FormCreate einbaue (habs mal getestet), kommt ein schöner Fehler.

DeddyH 18. Jan 2009 18:29

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Dann zeig doch mal die relevanten Quellcode-Stellen, bevor wir hier weiter in einer Blackbox herumstochern.

3_of_8 18. Jan 2009 18:31

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Gibst du das Bild auch wieder irgendwann frei?

DeddyH 18. Jan 2009 18:33

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Nur im Destruktor, hat er weiter oben gesagt.

SuperSeb 18. Jan 2009 18:47

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
@ 3_of_8:

Zitat:

[...] einmal im destructor.

@DeddyH: bitteschön:

Delphi-Quellcode:
initialization
  Klasse := TKlasse.Create(Klasse); //Ob das wohl so stimmt???
end.
Delphi-Quellcode:
//Klassendefinition habt ihr ja schon oben

constructor TKlasse.Create(AOwner: TComponent);
var
begin
  inherited Create(AOwner);
  Bild := TImage.Create(AOwner);
  with Bild do
  begin
    Parent := Self;
    Transparent := true;
    //usw. - alles, was man hier tun will, geht, ohne dass es beim Schließen einen Fehler erzeugt
  end;
end;

destructor TKlasse.Destroy;
begin
  Bild.Free; //da wirds gekillt
end;

Wenn ich jetzt in irgendwelche "hauseigenen" Prozeduren (z.B. wie oben procedure TKlasse.MachWas;) z.B. Bild.Top := 5; reinschreibe, dann gibts beim Schließen n Fehler

Was mich ja am Meisten fuchst, ist, dass - wenn ich die Passage aus der Prozedur rausnehme - sowohl "Bild" als auch das andere TImage-Objekt funktioniert

3_of_8 18. Jan 2009 18:49

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Okay. Du übergibst also dem Image einen Owner und gibst das Image frei, wenn deine Klasse freigegeben wird. Jetzt wird der Owner selbst freigegeben und hat noch das Image, um das er sich ja kümmern soll, und versucht es freizugeben. Was passiert, wenn man ein bereits freigegebenes Objekt nochmal freigeben will? Richtig, es kracht. :mrgreen:

Also: Übergib nil als Owner.

SuperSeb 18. Jan 2009 18:58

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Danke für deine Antwort.

Habe jetzt folgendes im Konstruktor stehn:

Delphi-Quellcode:
//...
Bild := TImage.Create(nil);
//...
...aber es kracht immer noch. Diemal sagt er (mal etwas konkreter): Exception der Klasse EInvalidPointer Meldung: "Ungültige Zeigeroperation"

Hmmm... Mist.

Was nu?

:glaskugel:

mkinzler 18. Jan 2009 19:01

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Hast du mal durch schrittweises Ausführen im Debugger versucht herauszufinden in welcher Zeile der Fehler auftritt?

gsh 18. Jan 2009 19:02

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Zitat:

Zitat von SuperSeb
@3_of_8: Also, bin jetzt Zeile für Zeile durchgesprungen - läuft ohne Probleme. Der Fehler tritt erst auf, wenn man die Form schließt

Kann es sein das du beim beenden die Klasse und somit das Bild freigibst aber dann noch mal drauf zugreifst.

Mach ambesten folgendes:
* Breakpoint bei der Position wo der Fehler kommt
* Breakpoint im Destroy von der Klasse

So nun schliesst du deine Exe und springst solange weiter bis du im Destroy angekommen bist. Wird der andere Breakpoint danach noch aufgerufen?

SuperSeb 18. Jan 2009 19:11

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Hurra, erster Erfolg: Er kommt tatsächlich noch mal da vorbei. Abver mir ist sehr schleierhaft, wo der Aufruf herkommen soll...
Die Prozedur, in der er vorbeikommt und wo der Fehler auftaucht wird nur bei einer Größenänderung (OnResize) und im Constructor aufgerufen...

:gruebel:

Edit: Nachtrag: Wenn ich das Bild.Free; aus dem Destructor rausnehme, gehts logischerweise. Aber das ist dann ja nicht mehr saubere OOP, oder?

3_of_8 18. Jan 2009 19:21

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Naja, ist im Prinzip auch egal, wenn das Programm beendet ist, wird der Speicher sowieso freigegeben. Aber ich frag mich auch, wieso das noch kracht - irgendwas ruft offenbar noch den Destruktor von dem Bild auf, aber wenn du keinen Owner übergibst, wer könnte das denn dann noch sein?

gsh 18. Jan 2009 19:22

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Zitat:

Zitat von SuperSeb
Hurra, erster Erfolg: Er kommt tatsächlich noch mal da vorbei. Abver mir ist sehr schleierhaft, wo der Aufruf herkommen soll...
Die Prozedur, in der er vorbeikommt und wo der Fehler auftaucht wird nur bei einer Größenänderung (OnResize) und im Constructor aufgerufen...

:gruebel:

Edit: Nachtrag: Wenn ich das Bild.Free; aus dem Destructor rausnehme, gehts logischerweise. Aber das ist dann ja nicht mehr saubere OOP, oder?

ok versuch noch folgendes:
Gebe deine Klasse nicht mit Bild.Free sondern mit FreeAndNil(Bild) frei.
Dann versiehst du jeden Aufruf von Bild mit:
Delphi-Quellcode:
if Bild <> nil then Bild.Irgendwas;

DeddyH 18. Jan 2009 19:27

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Deshalb auch meine Frage aus #5. Vermutlich wird die Klasse bereits an anderer Stelle freigegeben und nicht genullt. Da Free aber auf Assigned prüft, knallt es dann im Destruktor.

SuperSeb 18. Jan 2009 19:27

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Selbst die Krücke geht nicht...

bin so langsam am verzweifeln....

DeddyH 18. Jan 2009 19:32

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Jetzt prüf doch nochmal alles durch, ob
- die Klasse in jedem Fall erzeugt und
- sie nicht vor dem Aufruf des Destruktors freigegeben wird

turboPASCAL 18. Jan 2009 19:36

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Mal eine (blöde) Frage, um was für ein Bild handelt es sich denn ( JPEG ) ?

Ich frage deswegen:

ungefähres Zitat
... Wenn ich das mit einem anderem Bild mache, klappt es ...

himitsu 18. Jan 2009 19:46

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Zitat:

Zitat von SuperSeb
@himitsu: Also den AOwner habe ich durchgeschleift, d.h. das ist der des Klassen-Konstructors. Wahrscheinlich liegt hier der Hase im Pfeffer. Beim Erzeugen eines Objekts hatte ich dem Constructor schon mal Application mitgegeben, dann auch mal den eigenen Objektnamen. Es machte bisher keinen Unterschied und funktionierte Einwandfrei - habe auch schon gegooglet, aber so richtig schlau geworden, wo der Unterschied liegt, bin ich nicht.

Vielleicht sollte ich noch dazu sagen (jetzt werde ich wahrscheinlich gesteinigt), dass ich das Objekt unter initialization instanziere, denn wenn ich das erst bei FormCreate einbaue (habs mal getestet), kommt ein schöner Fehler.

OK, meinte zwar erstmal nur den Owner, welchen du beim .Create des Images übergibst,
aber wenn das auch "Klasse" ist, dann liegt da vermutlich wirklich das Problem.

PS: [TImage].Left greift auf dessen Owner zu ... drumm sollte da besser mal alles korrekt ablaufen!

Code:
[b]initialization[/b]
  [color=#ff0000]Klasse[/color] := TKlasse.Create([color=#0000ff]Klasse[/color]); //Ob das wohl so stimmt???
[b]end[/b].
und hier ... welchen Wert hat Klasse denn vorher?
ich vermute aber mal, daß Klasse irgendwo als eine globale Variable definiert ist, weswegen sie wohl zufällig den wert NIL enthält und warum es rein zufällt, bei diesem Aufruf nicht kracht. ([TImage].Create greift auch auf den Owner zu, wenn er existiert, also nicht NIL ist)

ja und Klasse is nicht Klasse ... es sind 2 unterschiedliche Inhalte.

SuperSeb 18. Jan 2009 20:01

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Also: 1. Ich arbeite da mit leeren Bildern, da ich nur die Hover- und OnClick- Eigenschaften brauche. Wenn dafür jemand ne bessere Idee hat, dann könnte ich das Ganze komplett umgehen.

Also sollte ich beim Create besser

Delphi-Quellcode:
Klasse := TKlasse.Create(Application);
schreiben, oder wie sonst?

mkinzler 18. Jan 2009 20:03

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
Ja oder Nil.

himitsu 18. Jan 2009 20:07

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
da hätte ja, statt TImage eine TPaintBox auch ausgereicht.

Was und vorallem wo willst du denn genau erreichen?

Wenn du z.B. auf einer Form einen sensitiven Bereich haben möchtest, dann reicht es auch OnMouseMove und OnMouseDown der Form zu erweitern und dort abhängig von der MousePosition zu reagieren.

SuperSeb 19. Jan 2009 12:37

Re: Zugriffsverletzung bei Adresse 00000000 bei TImage
 
So - habe es jetzt wieder gemacht, wie ichs vorher hatte. D.h. so wie im Post über diesem beschrieben. Das Problem bei der Art war, dass es beim Hovern geblinkt hat wie bescheuert. Die Lösung (eigentlich total simpel): es wurde zu oft neugezeichnet. Ne boolsche Variable her und gut war.

Trotzdem nochmal ganz herzlichen Dank an alle, die sich hier durch ihr Fachwissen ausgezeichnet und mir geholfen haben.

Gruß

Seb

:hello:


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