Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi AV bei Verwendung einer INI-File (https://www.delphipraxis.net/68188-av-bei-verwendung-einer-ini-file.html)

3_of_8 25. Apr 2006 22:35


AV bei Verwendung einer INI-File
 
Morgen.
Ich habe folgende Klassenfunktion, mit der ich die "ID" (ein von mir für jede meiner abgeleiteten Klassen vergebener Wert) aus einer INI-Datei auslese:

Delphi-Quellcode:
class function TModule.GetModuleID: Cardinal;
var ini: TIniFile;
begin
ini:=TIniFile.Create(ModuleConfigFile);
try
Result:=strtoint(ini.ReadString(ClassName,'ID','0'));
finally
ini.free;
end;
end;
Allerdings bekomme ich eine AV in der ntdll.dll.

Was könnte das bedeuten? Außerhalb dieser Klassenfunktion kann ich ohne Probleme aus der Datei lesen.

Hawkeye219 25. Apr 2006 22:49

Re: AV bei Verwendung einer INI-File
 
Zwei Fragen:

1.) Ist ModuleConfigFile ein Funktionsaufruf oder eine Variable? Falls es ein Funktionsaufruf ist, würde ich in der Funktion mal suchen.

2.) Warum benutzt du nicht ReadInteger statt ReadString?

Gruß Hawkeye

DevilsCamp 26. Apr 2006 06:51

Re: AV bei Verwendung einer INI-File
 
Zitat:

Zitat von Hawkeye219
Zwei Fragen:

1.) Ist ModuleConfigFile ein Funktionsaufruf oder eine Variable? Falls es ein Funktionsaufruf ist, würde ich in der Funktion mal suchen.

Und wenn es eine Variable ist, wo wird sie initialisiert? Steht auch der Name (+Pfad) der INI-Datei drin?

Hawkeye219 26. Apr 2006 07:45

Re: AV bei Verwendung einer INI-File
 
@DevilsCamp

Das war auch mein erster Gedanke. Abers selbst wenn die Variable leer ist oder ein unzulässiger Pfad drin steht, funktioniert der Zugriff auf die (nicht vorhandene) INI-Datei. Delphi liefert in diesem Fall einfach den angegebenen Defaultwert. Ich hatte eigentlich auch mit einer Exception gerechnet. :?

Gruß Hawkeye

DevilsCamp 26. Apr 2006 07:53

Re: AV bei Verwendung einer INI-File
 
hast Recht..

@3_of_8:
Hast du die AV immer oder nur bei einem bestimmten File?

jim_raynor 26. Apr 2006 09:38

Re: AV bei Verwendung einer INI-File
 
Wie rufst du denn die Methode auf? Ich hab so das Gefühl, dass er bei ClassName knallt. Also prüfe, ob du eine gültige Klasse beim Aufruf benutzt.

Muetze1 26. Apr 2006 09:52

Re: AV bei Verwendung einer INI-File
 
Zitat:

Zitat von jim_raynor
Also prüfe, ob du eine gültige Klasse beim Aufruf benutzt.

Meinst du eine gültige Instanz? Wenn ja: hinfällig, da es eine Class Procedure ist.

DevilsCamp 26. Apr 2006 09:55

Re: AV bei Verwendung einer INI-File
 
Zitat:

Zitat von jim_raynor
Wie rufst du denn die Methode auf? Ich hab so das Gefühl, dass er bei ClassName knallt. Also prüfe, ob du eine gültige Klasse beim Aufruf benutzt.

ClassName ist eine String-Variable.
Soviel kann man schon sagen, wenn man weiß, welche Parameter ReadString von TIniFile erwartet

GuenterS 26. Apr 2006 09:59

Re: AV bei Verwendung einer INI-File
 
Ich habe gerade versucht ClassName in einer class Procedure zu verwenden. Das funktioniert.

Bleibt diese ModuleConfigFile noch. Ist das vielleicht ein Property der Klasse?

jim_raynor 26. Apr 2006 10:35

Re: AV bei Verwendung einer INI-File
 
Zitat:

Zitat von GuenterS
Ich habe gerade versucht ClassName in einer class Procedure zu verwenden. Das funktioniert.

Ich habe ja auch nicht behauptet, dass es nicht funktioniert. Folgendes als Beispiel:

Delphi-Quellcode:
type
  TMyClass = class of TModule;

var
  MyClass: TMyClass;

begin
  MyClass:=nil;
  ShowMessage(IntToStr(MyClass.GetModuleID));
end;
könnte zu einer AV führe, da er ja keine gültige Klasse bekommen hat.

Und deshalb meine Bitte. Zeig mal den Aufruf der Funktion. Eventuell übergibts du ja nil als Objekt/Klasse.

p.S: Hab schon mitbekommen, dass es eine Klassenfunktion ist, aber trotzdem kann man mit dem obigen Konstrukt eine Übergabe von nil erreichen und das dürfte dann in einer AV in Classname verursachen, wenn dort keine prüfungen auf nil drin sind.

GuenterS 26. Apr 2006 10:39

Re: AV bei Verwendung einer INI-File
 
Zitat:

Zitat von jim_raynor
Zitat:

Zitat von GuenterS
Ich habe gerade versucht ClassName in einer class Procedure zu verwenden. Das funktioniert.

Ich habe ja auch nicht behauptet, dass es nicht funktioniert. Folgendes als Beispiel:

Delphi-Quellcode:
type
  TMyClass = class of TModule;

var
  MyClass: TMyClass;

begin
  MyClass:=nil;
  ShowMessage(IntToStr(MyClass.GetModuleID));
end;
könnte zu einer AV führe, da er ja keine gültige Klasse bekommen hat.

Und deshalb meine Bitte. Zeig mal den Aufruf der Funktion. Eventuell übergibts du ja nil als Objekt/Klasse.

p.S: Hab schon mitbekommen, dass es eine Klassenfunktion ist, aber trotzdem kann man mit dem obigen Konstrukt eine Übergabe von nil erreichen und das dürfte dann in einer AV in Classname verursachen, wenn dort keine prüfungen auf nil drin sind.

so ruft man aber keine class funktion auf

Delphi-Quellcode:
  var
    TMyClass = class(TObject)
    public
      class procedure Test;
    end;


... aufruf

    TMyClass.Test;

jim_raynor 26. Apr 2006 10:49

Re: AV bei Verwendung einer INI-File
 
Selbst, wenn der Aufruf so nicht möglich ist (was ich kaum glaube, hab aber kein Delphi da um es zu überpüfen) kannst du auf jeden Fall folgendes machen:

Delphi-Quellcode:
var
  Module: TModule;

begin
  Module:=nil;
  ShowMessage(IntToStr(Module.GetModuleID));
end;
Und es würde mich stark wundern, wenn er dann bei ClassName nicht knallt. Aber back to topic. Meine Vermutung ist, dass beim Aufruf von GetModuleID eine ungültige Klassen-/Objektreferenz vorliegt wodurch er in ClassName knallt. Allerdings kann man das erst mit Gewissheit sagen, wenn Manuel ein wenig mehr Quellcode zeigt ;)

DevilsCamp 26. Apr 2006 10:52

Re: AV bei Verwendung einer INI-File
 
Wieso hängt Ihr euch eigentlich daran auf, dass die Variable ClassName heißt?

TIniFile.ReadString erwartet an erster Stelle einen STRING und nichts anderes!!!!

Daher erneut meine Frage an 3_of_8:
Hast du diese Probleme auch in anderen Projekten oder nur dort?

Aenogym 26. Apr 2006 10:55

Re: AV bei Verwendung einer INI-File
 
Zitat:

Zitat von DevilsCamp
Wieso hängt Ihr euch eigentlich daran auf, dass die Variable ClassName heißt?

weil ClassName ein funktion ist.

Hawkeye219 26. Apr 2006 11:07

Re: AV bei Verwendung einer INI-File
 
Hallo,

jim_raynor hat Recht. Der Zugriff über einen Klassenzeiger führt nicht zum Fehler, der Zugriff über eine NIL-"Instanz" aber wohl. Manuel greift offenbar über eine nicht initialisierte Variable vom Typ TModule (oder eines Nachfolgers) auf die ID zu und erhält dann die beschriebene Fehlermeldung.

Gruß Hawkeye

GuenterS 26. Apr 2006 11:49

Re: AV bei Verwendung einer INI-File
 
Okok. Es funktioniert beides (compilierbar), wobei das mit dem nil Pointer ne AV gibt.

Nur wissen wir immer noch nicht, wie er denn nun die Funktion aufruft.

3_of_8 26. Apr 2006 11:56

Re: AV bei Verwendung einer INI-File
 
Also:

ModuleConfigFile ist ein String, der in dem Initialization-Abschnitt einer referenzierten Unit zugewiesen wird. Die Datei existiert definitiv.

Ich verwende deshalb nicht ini.ReadInteger, weil die ID als Hex-Zahl vorliegt ($0101) und ich mir nicht sicher bin, ob ReadInteger das erkennt.

Ich glaube das Problem ist, dass

TModuleClass(Pointer(ModuleButtons[I])).ClassName;

Immer ein Leerstring ist.

GuenterS 26. Apr 2006 12:07

Re: AV bei Verwendung einer INI-File
 
aha.

Du rufst in dem Beispielcode wo doch der Fehler liegen sollte nirgends TModuleClass(Pointer(ModuleButtons[I])).ClassName; auf?

Wieso ist das ein Problem, wenn dir das einen Leerstring liefert?

Vielleicht dürfen wir etwas mehr von dem sehen, was den Fehler verursacht.

Muetze1 26. Apr 2006 12:10

Re: AV bei Verwendung einer INI-File
 
Du hast eine Klasse, welche eine statische Methode hat. Diese verwendet eine Variable (glaubst du zumindest), namens ClassName. Diese Variable hast du irgendwo global deklariert (in der Klasse kann nicht sein, da du in einer statischen Methode keinen Zugriff auf Klassenvariablen hast). So, da du nun aber dich in einer statischen Methode befindest, nimmt er in deiner Methode natürlich erstmal das naheliegenste, sprich: wenn vorhanden, das Element im aktuellen Gültigkeitsbereich. Dieses wäre dann _nicht_ die globale Variable ClassName sondern die in TObject definierte statische Methode namens "ClassName", welche einen String zurück gibt.

Wie man nun an der Definition von ReadString von TIniFile erkennen sollte, dass er nicht die ClassName Methode nimmt ist mir zwar schleierhaft, aber man lässt sich ja gerne belehren...

So, das nur noch mal zum Hinweis. Grundlegend bringt es uns nicht weiter, da beides eine statische Methode ist und somit ein gültiges Konstrukt, auch wenn er vllt. nicht wie gewünscht die globale Variable sondern die Methode nutzt.

Und zum anderen Frage ich mich, was diese ( TModuleClass(Pointer(ModuleButtons[I])).ClassName; ) abenteuerliche Konstruktion von nöten macht?

3_of_8 26. Apr 2006 12:10

Re: AV bei Verwendung einer INI-File
 
Delphi-Quellcode:
for I:=0 to high(ModuleButtons) do
begin
  showmessage(TModuleClass(Pointer(ModuleButtons[I])).ClassName);
  bitmap:=TBitmap.Create;
  bitmap.LoadFromResourceName(HINSTANCE,
  TModuleClass(Pointer(ModuleButtons[I].Tag)).ClassName);
  CreateCursorFromBMP(TModuleClass(Pointer(ModuleButtons[I])).
  GetModuleID(TModuleClass(Pointer(ModuleButtons[I])).ClassName),bitmap);
end;
EDIT:

Also. Ich habe KEINE Variable namens ClassName. Ich will diese statische Methode haben.

Ich füge einem Panel mit einer Prozedur mehrere Buttons hinzu, jeder steht für eine Klasse abgeleitet von TModule. Im Tag desselben steckt ein Pointer auf eine class of TModule.

Später lese ich das wieder aus und erzeuge eine Instanz:

module:=TModuleClass(Pointer((Sender as TComponent).Tag));

Muetze1 26. Apr 2006 12:13

Re: AV bei Verwendung einer INI-File
 
Mal castest du ModuleButtons[I].Tag, mal ModuleButtons[I] auf einen Pointer und dann auch TModuleClass - was denn nun?

Und von was für einem Typ ist das Array ModuleButtons?

/EDIT: Vermutlich wird der komische TypeCast von Tag (der wohl 0 ist) auf einen Pointer ein Nil Pointer der zum Nil TModuleClass wird. Also nochmal: Warum überhaupt so komisches Konstrukt? Warum die Typensicherheit so über Board werfen?

Muetze1 26. Apr 2006 12:19

Re: AV bei Verwendung einer INI-File
 
Zitat:

Zitat von 3_of_8
Später lese ich das wieder aus und erzeuge eine Instanz:

module:=TModuleClass(Pointer((Sender as TComponent).Tag));

Damit erzeugst du keine Instanz.

Damit würdest du eine Instanz der in dem Tag enthaltene Class Of TModule Ableitung der Class of bekommen.
Delphi-Quellcode:
module := TModuleClass(Pointer((Sender as TComponent).Tag)).Create;
bzw. Wenn Module vom Typ Class of TModule ist, dann erzeugst damit eine Instanz:

Delphi-Quellcode:
 Instanz := Module.Create;

alcaeus 26. Apr 2006 12:37

Re: AV bei Verwendung einer INI-File
 
Zitat:

Zitat von 3_of_8
Also. Ich habe KEINE Variable namens ClassName. Ich will diese statische Methode haben.

Ich will auch...die Deklaration der Klasse sehn.
Wenn die Klasse naemlich von TObject abgeleitet ist (was sie immer ist), dann hast du zwar keine Variable namens ClassName, dafuer aber eine Funktion ClassName() von TObject. Allerdings gibt mir die Funktion auch bei einer class function den Klassennamen zurueck.

Was willst du denn eigentlich tun/erreichen?
Und warum castest du ModuleButtons[i] auf Pointer, dann auf TModuleClass, anstatt direkt ein Objekt von TModuleClass abzuspeichern? :gruebel: Irgendwie ist das krass konfus....
BTW, dieser Aufruf:
Delphi-Quellcode:
TModuleClass(Pointer(ModuleButtons[I].Tag)).ClassName
liefert immer "TModuleClass" zurueck, schliesslich castest du auf TModuleClass. Ich verstehe deine Art zu programmieren irgendwie ueberhaupt nicht :gruebel:

Greetz
alcaeus

3_of_8 26. Apr 2006 13:54

Re: AV bei Verwendung einer INI-File
 
TModuleClass ist eine Class of TModule. Wenn ich dann eine Instanz davon erzeute, erzeuge ich eine Instanz eines abgeleiteten Typs von TModule. Ich will einfach beim Klick auf einen SpeedButton die damit verbundene Klasse instantiieren. Das ganze soll dynamisch und leicht erweiterbar sein.

Das funktioniert auch prima, bis darauf, dass ich in der class function GetModuleID keine INI-Datei verwenden kann. Das ist mein Problem.

Wenn ich wüsste, was die ntdll.dll macht, wäre es evtl. auch einfacher.

Und die Deklaration der Klasse steht nebenbei in meinem ersten Beitrag.

Ich will mit ClassName den Namen der Klasse, so wie ihn ClassName() zurückgibt.

Muetze1 26. Apr 2006 14:03

Re: AV bei Verwendung einer INI-File
 
Ich zweifle an, dass man eine Metaklasse in einen Tag verbannen kann, da diese keine Instanzen haben sondern eine Typinformation sind. Kann man wirklich eine Ableitung von TModule als Klasse in einem Tag unterbringen? Die Elemente von TModuleClass sind doch keine Instanzen und somit keine Zeiger, daher die Frage ob man sie wirklich in einem Tag ablegen kann.

Ich glaube das das grundlegende Problem nicht in der GetModuleID liegt, sondern in dem Aufruf bzw. dem drumherum.

jim_raynor 26. Apr 2006 14:07

Re: AV bei Verwendung einer INI-File
 
Die ntdll.dll ist der Kernel von Windows! Wenns da knallt, dann liegst nicht an der DLL selbst ...

Also versuchen wir es nochmal.

1. Wie ist ModuleButtons definiert? Wenn es als Array of TModuleClass definiert ist, dann kannst du das ganze gecaste sparen. Wenn nicht, frage ich mich ernsthaft warum nicht!

2. Wo und wie wird ModuleButtons gefüllt?

3. Ist es wirklich sehr sehr sehr verwunderlich, dass du mal:

Delphi-Quellcode:
TModuleClass(Pointer(ModuleButtons[I])).ClassName
und mal

Delphi-Quellcode:
TModuleClass(Pointer(ModuleButtons[I].Tag)).ClassName
Jetzt wo ich länger drüber nachdenke, gehe ich mal stark davon aus das du überall noch das .Tag ergänzen musst ;)

Khabarakh 26. Apr 2006 14:11

Re: AV bei Verwendung einer INI-File
 
Zitat:

Zitat von Muetze1
Ich zweifle an, dass man eine Metaklasse in einen Tag verbannen kann, da diese keine Instanzen haben sondern eine Typinformation sind.

Und diese Typinformation hat einen eindeutigen Ort im Arbeitsspeicher, also ist das, was 3_of_8 da veranstaltet, eigentlich problemlos möglich.
Delphi-Quellcode:
i := Integer(TMouse);
  ShowMessage(TClass(i).ClassName);
Ansonsten schließe ich mich jim_raynor an, in diesen Fragen wird wohl der Knackpunkt liegen.

3_of_8 26. Apr 2006 17:35

Re: AV bei Verwendung einer INI-File
 
Ich sage es nochmal: das ganze funktioniert wunderbar, bis auf das INI-File, wobei irgendwas mit ClassName() nicht hinhaut.

Das .Tag habe ich nur hier vergessen, in meinem Code stimmt das UND ES FUNKTIONIERT AUCH.

ModuleButtons ist ein array of TSpeedButton.

Khabarakh 26. Apr 2006 17:45

Re: AV bei Verwendung einer INI-File
 
Und alle Tags sind wirklich ungleich null?

mirage228 26. Apr 2006 18:04

Re: AV bei Verwendung einer INI-File
 
Hi,

Ich hatte den selber mit INIs auch mal. Du darfst für den ersten Parameter auf gar keinen Fall einen Leerstring (oder einen string der nur aus Leerzeichen besteht) zurückgeben, sonst knallts in der ntdll.dll (zumindest unter XP)!

Siehe: http://qc.borland.com/wc/qcmain.aspx?d=9487

mfG
mirage228

3_of_8 26. Apr 2006 18:44

Re: AV bei Verwendung einer INI-File
 
OK, Problem: Wieso gibt TModuleClass(Pointer(ModuleButtons[I].Tag)).ClassName einen Leerstring zurück? Und warum nur an dieser Stelle und sonst nicht? Mir schwirrt der Kopf.

Edit: É voila! Auf einmal gehts! Hab tatsächlich das .Tag vergessen und das ganze jetzt so umgangen, dass der Funktion mit dem INI-File ihr eigener Klassenname übergeben wird. Ich versteh zwar immer noch nicht, warum es manchmal mit ClassName() funktioniert und manchmal nicht, aber mit diesem Workaround gehts jetzt endlich.


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