[Delphi] Fatal exception bij aanroep Inherited Create

Pagina: 1
Acties:

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 16-10-2025
Skipping de introductie en ik ga gelijk door naar t probleem :P

Ik ben een programma aan bouwen, waarbij ik een eigen klasse TPlayer heb gemaakt.
Deze erft van TObject.

Nu krijg ik bij het aanroepen van de Create van deze klasse de volgende foutmelding
---------------------------
Debugger Exception Notification
---------------------------
Project biljart.exe raised exception class EAccessViolation with message 'Access violation at address 0040347D in module 'biljart.exe'. Read of address 00000000'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
Deze vindt plaats op de volgende regel in mn code.
Tjah, eigenlijk kwam de regelhighlight op die regel van Fhistory, maar uit ervaring en d.m.v de comment die ik er nu heb voorgezet, weet ik dat het op de regel ervoor plaatsvindt.
code:
1
2
3
4
5
constructor TPlayer.Create;
 begin
   inherited Create; //deze regel vindt de foutmeling plaats
   //Fhistory := TStack.Create;
 end;


Ik volg het dus niet meer, ik snap niet waarom deze melding plaatsvindt en ik heb het gevoel dat het iets vrij stoms is wat ik over het hoofd zie. Ik programmeer nog niet zo lang in delphi dus dat zou best kunnen :P
Ik heb zelf al meerdere units met classes geschreven waarbij ik op dezelfde manier gebruik maak van Create als het bovenstaande, en dit gaat wel goed. (wat dus mijn verwarring nu vergroot :P) Ik heb de delphi help er al op nageslagen, en andere units bekeken, maar kan geen fouten ontdekken in mijn code.

Ik zal hieronder nog even de kop van de TPlayer unit neerzetten voor referentie.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
unit Speler;

interface

uses Contnrs, SysUtils, StrUtils;

Type
  TPlayer = class(TObject)
  private
    FNaam : String;
    FScore : Integer;
    FhoogsteSerie : Integer;
    FCaramboles : Integer;
    Fgemiddelde : Real;
    //Fhistory : TStack;
    function getGem: String;
    procedure setNaam(name : String);
    procedure setScore(waarde : Integer);
    procedure setHoogste(waarde : Integer);
    procedure setGem(waarde : Real);
    procedure setCaramboles(waarde : Integer);

  public
    constructor Create;
    destructor Destroy;
    property Naam: String read FNaam write setNaam;
    property Score: Integer read FScore write setScore;
    property hoogsteSerie: Integer read FhoogsteSerie write setHoogste;
    property Caramboles: Integer read FCaramboles write setCaramboles;
    property gemiddelde: Real read Fgemiddelde write setGem;
    //property history : TStack read Fhistory;
    procedure undo();
  end;


Dus als iemand mij zou kunnen helpen... graag

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Is TObject niet een abstracte klasse, en kun je er daarom gewoon geen instantie van maken?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • D-Raven
  • Registratie: November 2001
  • Laatst online: 16-10-2025
Dat klopt, maar ik maak er ook geen instantie van.
Ik erf ervan d.m.v de regel
code:
1
TPlayer = class(TObject)


Daarna wil ik met "inherited Create;" de create methode van de superklasse van TPlayer aanroepen.
(TObject dus) welke dan volgens documentatie, mijn object zou initialiseren.
Of ik moet iets wel heel erg verkeerd begrepen hebben.

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 06-03 20:19

_Thanatos_

Ja, en kaal

Het enige dat ik me kan voorstellen, is dat je (perongeluk hoop ik) zoiets doet
Delphi:
1
2
3
4
var Player: TPlayer;
begin
Player := Player.Create;
end;

De AccessViolation is een welbekende "read of address 00000000", wat betekent dat je iets met een nil-pointer probeert te doen. Vandaar dat ik bovenstaande verdenk.

Trouwens, wil je als de sodemieter je destructor markeren met override? Anders wordt hij niet aangeroepen wanneer je Player.Free aanroept ;)

[ Voor 6% gewijzigd door _Thanatos_ op 11-04-2005 14:31 ]

日本!🎌


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 08-05 19:24

alienfruit

the alien you never expected

Mjah, wordt wel aangeroepen alleen zijn FHistory wordt niet opgeruimd ;)

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 16-10-2025
_Thanatos_ schreef op maandag 11 april 2005 @ 14:29:
Het enige dat ik me kan voorstellen, is dat je (perongeluk hoop ik) zoiets doet
Delphi:
1
2
3
4
var Player: TPlayer;
begin
Player := Player.Create;
end;

De AccessViolation is een welbekende "read of address 00000000", wat betekent dat je iets met een nil-pointer probeert te doen. Vandaar dat ik bovenstaande verdenk.

Trouwens, wil je als de sodemieter je destructor markeren met override? Anders wordt hij niet aangeroepen wanneer je Player.Free aanroept ;)
Ik d8 dat je met override alleen maar aangeeft dat die overschreven kan worden in subklasses, en dus meedoet met polymorphisme.(aangezien ik dat niet ga doen met deze klasse heb ik het daarom niet opgenomen)

En ja.... dat player := player.create is idd wat ik doe :X:X:X
Zei toch dat t waarschijnlijk iets stoms zou zijn :P. Ik wil dus van een (nog) nietbestaand object zijn create methode aanroepen. Zeer slim Raaf 8)7 8)7

Verwijderd

Bij directe afgeleiden van TObject hoef je niet de inherited constructor/destroy aan te roepen. Uit de Delphi source:
Delphi:
1
2
3
4
5
6
7
constructor TObject.Create;
begin
end;

destructor TObject.Destroy;
begin
end;

Niks dus. :)

Ik gok dat _Thanatos_ 't bij het goede eind heeft.

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 08-05 19:24

alienfruit

the alien you never expected

Ik d8 dat je met override alleen maar aangeeft dat die overschreven kan worden in subklasses, en dus meedoet met polymorphisme.(aangezien ik dat niet ga doen met deze klasse heb ik het daarom niet opgenomen)
Nee, dat is "virtual" hiermee kun bij een afgeleidde deze method overschrijven, virtual; abstract; maakt er dan een placeholder van.

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 06-03 20:19

_Thanatos_

Ja, en kaal

alienfruit schreef op maandag 11 april 2005 @ 14:58:
[...]


Nee, dat is "virtual" hiermee kun bij een afgeleidde deze method overschrijven, virtual; abstract; maakt er dan een placeholder van.
Of "dynamic", maar het verschil met "virtual" heb ik zelf nooit begrepen :)

日本!🎌


Verwijderd

Uit Delphi in a nutshell:
Instead of using the virtual directive, you can also use the dynamic directive. The semantics are identical, but the implementation is different. Looking up a virtual method in a VMT is fast because the compiler generates an index directly into a VMT. Looking up a dynamic method is slower. Calling a dynamic method requires a linear search of a class's dynamic method table (DMT).

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

En waarom zou je dan dynamic gebruiken als het toch langzamer is? Omdat een VMT meer ruimte in neemt als een DMT. Er wordt dus over het algemeen geadviseerd om alleen dynamic te nemen in de gevallen waar een method bijna nooit geoverride wordt.

We adore chaos because we like to restore order - M.C. Escher


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 08-05 18:37

Tomatoman

Fulltime prutser

Uit de Delphi helpfiles:
Virtual versus dynamic
Virtual and dynamic methods are semantically equivalent. They differ only in the implementation of method-call dispatching at runtime. Virtual methods optimize for speed, while dynamic methods optimize for code size.

In general, virtual methods are the most efficient way to implement polymorphic behavior. Dynamic methods are useful when a base class declares many overridable methods which are inherited by many descendant classes in an application, but only occasionally overridden.

Note
Only use dynamic methods if there is a clear, observable benefit. Generally, use virtual methods.
Dynamic gebruik ik over het algemeen als ik een statische method implementeer, maar de mogelijkheid open wil houden dat iemand hem ooit nog wil overriden. Ik verwacht dus niet dat iemand dat daadwerkelijk gaat doen, maar sluit het niet uit.

Ik meen mij te herinneren dat dynamic minstens net zo snel is als virtual, zolang je maar geen override doet. Is er iemand die dit kan bevestigen of ontkrachten?

Een goede grap mag vrienden kosten.


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Verwijderd schreef op maandag 11 april 2005 @ 14:42:
Bij directe afgeleiden van TObject hoef je niet de inherited constructor/destroy aan te roepen. Uit de Delphi source:
Delphi:
1
2
3
4
5
6
7
constructor TObject.Create;
begin
end;

destructor TObject.Destroy;
begin
end;

Niks dus. :)

Ik gok dat _Thanatos_ 't bij het goede eind heeft.
Hoeft inderdaad niet, maar misschien wel slim. Mochten ze in de toekomst er toch code neer gaan zetten dan blijft jou code correct werken.

Natuurlijk zijn er uitzonderingen.

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 08-05 18:37

Tomatoman

Fulltime prutser

Kaassoevlee schreef op maandag 11 april 2005 @ 23:32:
[...]

Hoeft inderdaad niet, maar misschien wel slim. Mochten ze in de toekomst er toch code neer gaan zetten dan blijft jou code correct werken.

Natuurlijk zijn er uitzonderingen.
De constructor van TObject is niet virtual, zodat je die niet hoeft te overriden en ook niet via inherited hoeft aan te roepen. De destructor is daarentegen wel degelijk virtual, dus hoor je die te overriden en met inherited aan te roepen.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type
  TObjectDescendant = class(TObject)
    constructor Create; { mag eventueel als virtual worden gedeclareerd }
    destructor Destroy; override;
  end;

constructor TObjectDescendant.Create; 
begin 
  // constructor implementatie
end; 

destructor TObjectDescendant.Destroy; 
begin 
  // destructor implementatie
  inherited; // inherited Destroy aanroepen
end;

Een goede grap mag vrienden kosten.


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

De constructor van TObject is inderdaad niet virtual. Maar stel dat er code staat in de constructor van TObject en jij maakt een eigen contructor, dan kun je met inherited de code in de contructor van TObject aanspreken (of juist niet).
Heeft volgens mij weinig te maken met of de constructor van TObject wel of niet virtual is, immers je spreekt toch (bijna) altijd je eigen constructor aan.

[ Voor 9% gewijzigd door jelmervos op 12-04-2005 09:10 ]

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Icelus
  • Registratie: Januari 2004
  • Niet online
tomatoman schreef op maandag 11 april 2005 @ 20:23:
Uit de Delphi helpfiles:
[...]

Dynamic gebruik ik over het algemeen als ik een statische method implementeer, maar de mogelijkheid open wil houden dat iemand hem ooit nog wil overriden. Ik verwacht dus niet dat iemand dat daadwerkelijk gaat doen, maar sluit het niet uit.

Ik meen mij te herinneren dat dynamic minstens net zo snel is als virtual, zolang je maar geen override doet. Is er iemand die dit kan bevestigen of ontkrachten?
Virtual vs. Dynamic
For starters, we now have two ways to indicate whether or not a method can be overrided in a descendant class. We can use either virtual or dynamic. The difference is the algorithm that is used to find the correct (polymorphic) method at run-time. Using virtual, the compiler will find the correct method by walking the VMT of the instance. Using dynamic, the compiler will use another algorithm, that uses less storage space, but is slower. So, again we see here a trade-off between size and speed, and Delphi offers us the chance to make our own decisions about it! If we want a small program, or need a faster one, check our virtual and dynamic routines, and see if we can gain the one we desire.

It turns out that a dynamic method is about 50% slower than a virtual method call. Note that this only tells us something about the call, since the actual work inside the polymorphic routine has to be taken into account as well in a real-world situation.
Bron

Developer Accused Of Unreadable Code Refuses To Comment

Pagina: 1