AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte
Thema durchsuchen
Ansicht
Themen-Optionen

Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

Ein Thema von DSCHUCH · begonnen am 11. Feb 2013 · letzter Beitrag vom 14. Feb 2013
Antwort Antwort
Seite 2 von 3     12 3      
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.366 Beiträge
 
Delphi 10.3 Rio
 
#11

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 11. Feb 2013, 22:03
hier mal ein einfaches bsp.
Was zum Geier ist daran einfach? Zudem greifst Du wieder nicht auf ein Feld/Variable der nicht instanziierten Klasse zu.


Delphi-Quellcode:


  TTest = class(TObject)
  private
    FTestProperty: Integer;
  public
    procedure DoSomething;
    function DoAnything: Integer;
    property TestProperty: Integer read FTestProperty write FTestProperty;
  end;


function TTest.DoAnything: Integer;
begin
  result := FTestProperty + 1;
end;

procedure TTest.DoSomething;
begin
  ShowMessage('Hallo Welt');
end;


procedure TForm1.Button1Click(Sender: TObject);
var Test: TTest;
begin
  Test.DoSomething;
  Test.TestProperty := 10;
  ShowMessage(IntToStr(Test.DoAnything));
end;


Und jetzt das Entscheidende: Schalte die Optimierung von Delphi aus! Sonst bekommst Du erst am Ende einen Zugriffsfehler!
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#12

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 11. Feb 2013, 22:07
Klar geht das. Eine Methode ist eben auch nur Code.
Sicher, es ist böse und risikoreich - aber es lassen sich eben auch schlechte Programme compilieren.

Mit ein bisschen Glück bekommst du aber eine Warning in der sowas steht wie "Zugriff auf nicht initialisierte Variable" oder so.

Falls du natürlich auf Daten der Klasse zugreifst ist das noch viel böser und fliegt dir im besten Falle sofort mit einer AV um die Ohren
  Mit Zitat antworten Zitat
DSCHUCH

Registriert seit: 6. Jun 2007
Ort: Dresden
185 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#13

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 11. Feb 2013, 22:21
Was zum Geier ist daran einfach?
worum es geht ist denke ich klar.

Zudem greifst Du wieder nicht auf ein Feld/Variable der nicht instanziierten Klasse zu.
das ist ja genau der Punkt. Es ist absoluter zufall und partout nicht nachvollziehbar, woher ein fehler kommt. wir haben zB derzeit einen stacktrace eines fehlers, natürlich 1-2 mal die Woche (oder auch nicht), wo zig klassen und property-reader vorkommen. somit is nicht mehr nachvollziehbar, wo der fehler eigentlich entstanden ist. ich kann nur dann, wenn ich jetzt genau jede klasse untersuche und nachschaue wo auf reader und wo das erste mal auf eine interne variable zugegriffen wird bewerten, wo es theoretisch sein könnte. habe ich den quellcode nicht, ist es gar nicht nachvollziehbar.

interessant wird es umso mehr, wenn man klassen weiterentwickelt. so habe ich zB in der vergangenheit manchmal klassenvariablen zu properties verändert, um eine nachträgliche vererbung zu implementieren.

Delphi-Quellcode:
zB: TMyClassNew und TMyClassOld implementieren beide ein und dasselbe Interface.

class Base=class
 FistVersionVar : TMyClass;
end; //alte version

class BaseV1=class(Base)
 property FirstVersionVar : TMyClassOld read FGetMyClass;
end;

class BaseV2=class(Base)
 property FirstVersionVar : TMyClassNew read FGetMyClass;
end;
Und jetzt das Entscheidende: Schalte die Optimierung von Delphi aus! Sonst bekommst Du erst am Ende einen Zugriffsfehler!
[/QUOTE]

was ändert das muß ich jetzt fragen? erhalte ich dann einen anderen stack trace/ die AV an einer anderen stelle?
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.366 Beiträge
 
Delphi 10.3 Rio
 
#14

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 11. Feb 2013, 22:55
Zudem greifst Du wieder nicht auf ein Feld/Variable der nicht instanziierten Klasse zu.
das ist ja genau der Punkt. Es ist absoluter zufall und partout nicht nachvollziehbar, woher ein fehler kommt.
ich habe irgend wie das Gefühl wir reden aneinander vorbei...

Und jetzt das Entscheidende: Schalte die Optimierung von Delphi aus! Sonst bekommst Du erst am Ende einen Zugriffsfehler!
was ändert das muß ich jetzt fragen? erhalte ich dann einen anderen stack trace/ die AV an einer anderen stelle?
ja. Der kommt an einer anderen Stelle - eben weil der Optimierer bei schlechtem Code Blödsinn macht.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#15

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 12. Feb 2013, 00:06
Der Hintergrund ist folgender: Der Code jeder Klasse besteht immer. Eine Klasse ist im Speicher nichts weiter, als ein Stück Feld-Definitionen für den Fall der Instanziierung, und ein Stück, in dem alle Methoden inkl. deren Code steht. Eine Instanz bekommt NICHT je ihre ganz eigene Kopie des Codes, sondern verweist immer nur auf die Speicherstelle, an der die Klassendefinition sie stehen hat. (Bzw. die jeweilige Elternklasse, oder es wird die VMT bemüht wenn es um virtuelle Methoden geht.) Der Code ist ab Programmstart einfach IMMER da. Die Felder auf die ggf. zugegriffen wird, sind es jedoch nicht.
Weist man also einer Variablen eine Instanz zu und zerstört diese ohne "nillen", so hat man wunderbar nachher Zugriff auf die Methoden, selbst wenn der Speicher der Instanz längst überschrieben wurde. Der Compiler weiss ja von welchem Typ die Referenz ist, und verweist munter auf die jeweiligen Stellen im Code-Segment, völlig egal ob da eine Instanz ist oder nicht.

Technisch gesehen ist dies sogar nichtmals ein Fehler, da die Methoden ja da sind! Da man (der Compiler) nicht immer 100%ig wissen kann, ob in diesen auf Felder zugegriffen wird, die möglicherweise nicht existieren, geht das auch durch den Compiler. Im günstigsten Fall mit Warnung, aber an und für sich ist da aus technischer Sicht nichts falsch dran. Man muss halt aufpassen. Und ja, das ist in anderen Sprachen auch so, wenn gleich einige solche Dinge besser erkennen können, und ggf. gleich ganz die Kompilierung untersagen. Zwingend ist das nicht.

Statische Methoden sind unter der Haube fast mit "normalen" identisch. Hier sagt man dem Compiler nur explizit: Wenn das hier aufgerufen wird, stelle mir bitte sicher, dass ich nur auf Dinge zugreife, die bereits mit der nackten Klassendeklaration in Existenz gerufen wurden! (Also andere statische Methoden für die das sicher gestellt wurde, und Klassenvariablen.) (Zudem lassen diese sich dann über den Namespace der Klasse aufrufen, nicht (nur) über eine Instanz-Referenz.) Ansonsten stehen die genau so im Codesegment wie alles andere auch. (Und, Spezialfall Delphi, "self" wird anders behandelt.)

TL;DR: Der Code ist immer da, und steht genau ein Mal pro Klasse im Speicher (egal wie viele Instanzen). Er wird immer nur von dieser einen Stelle aus aufgerufen, der Compiler ist dafür verantwortlich. Eine Instanz braucht es für den blanken Aufruf nicht, der Code ist schließlich vorhanden. Manche Sprachen prüfen sowas strikter ab, es ist aber nur ein formaler/semantischer Fehler - kein technischer/syntaktischer. Manche stellen sowas in die Verantwortung des Programmierers (und warnen ggf.), andere versuchen das ganz zu unterbinden (wodurch manche Hacks allerdings auch unmöglich werden). Delphi gehört zu ersterem, und das ist völlig in Ordnung.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium (12. Feb 2013 um 00:09 Uhr)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#16

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 12. Feb 2013, 06:50
Man muss eben wissen, das Delphi nicht das Modernste an Programmiersprache ist, was es auf der Welt gibt. Da kommt sowas schon mal vor.

Abhilfe:
1. Ordentlich programmieren (Erzeugerprinzip verwenden, d.h. wer instantiiert, gibt auch frei)
2. Unit-Tests
3. FastMem einbauen

Nicht instantiierte Objekte hatte ich sehr selten (z.B. wenn ein Objekt per Message weitergeleitet wird und nicht klar ist, wie lange es lebt). Aber das ist ja auch ein Verstoß gegen (1)


Ich glaube, FastMem findet die Fehler, bei denen ein nicht instantiiertes Objekt verwendet wird.
  Mit Zitat antworten Zitat
DSCHUCH

Registriert seit: 6. Jun 2007
Ort: Dresden
185 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#17

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 12. Feb 2013, 19:48
hm... technisch ist klar, was wie wo und warum.

andererseits ist mir jetzt auch klar, wieso ich noch nie eine (komplexere) delphi anwendung ohne AV gesehen habe, selbst die IDE immermal knallt mit den sinnlosesten fehlermeldungen von den blödsinnigsten units/zeilen etc.

1) was mich jetzt noch mal interessiert ist, wie dann eigentlich proceduren implementiert sind, welche auf (windows-) messages reagieren (zB Painter). da der code ja immer vorhanden ist, unabhängig der klasseninstanz, muß ja irgendwo geregelt werden, welche instanz nun die message erhält, und welche nicht. ist es theoretisch vorstellbar, das eine nil-klasse eine message (zB wm_paint) erhält?

2) was ändern FastMem bzw. die Code Optimierung an dem ganzen?
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#18

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 12. Feb 2013, 20:49
hm... technisch ist klar, was wie wo und warum.
Angesichts deiner weiteren Ausführungen zweifle ich, ob Du es wirklich begriffen hast.
Zitat:
andererseits ist mir jetzt auch klar, wieso ich noch nie eine (komplexere) delphi anwendung ohne AV gesehen habe, selbst die IDE immermal knallt mit den sinnlosesten fehlermeldungen von den blödsinnigsten units/zeilen etc.
Das schmerzt. Ich sehe das bei *jedem* Programm, egal in welcher Sprache.

Zitat:
2) was ändern FastMem bzw. die Code Optimierung an dem ganzen?
Alter Schwede. FastMem *zeigt* dir den Fehler (steht auch im Beitrag) und der Optimierer (steht auch da) sorgt eben beim 'wegkürzen' von Code dafür, das der Fehler u.U. in einer anderen Stelle angezeigt wird. Seufz.

Dir fehlen entscheidende Grundlagen, um hier mitreden bzw. kritisieren zu können. Schreib einfach saubere Programme, das ist schon schwer genug.
  Mit Zitat antworten Zitat
Benutzerbild von JamesTKirk
JamesTKirk

Registriert seit: 9. Sep 2004
Ort: München
604 Beiträge
 
FreePascal / Lazarus
 
#19

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 13. Feb 2013, 08:54
1) was mich jetzt noch mal interessiert ist, wie dann eigentlich proceduren implementiert sind, welche auf (windows-) messages reagieren (zB Painter). da der code ja immer vorhanden ist, unabhängig der klasseninstanz, muß ja irgendwo geregelt werden, welche instanz nun die message erhält, und welche nicht. ist es theoretisch vorstellbar, das eine nil-klasse eine message (zB wm_paint) erhält?
Innerhalb des Constructors eines Formulars wird die WndProc gesetzt, welche von Windows die Nachrichten enthält. Diese Nachrichten werden dann (einfach formuliert) per Form.Dispatch an das jeweilige Form geschickt. Dispatch ist in TObject deklariert und sucht sich an Hand der Nachrichtentabelle des Objekts die passend message Methode raus oder ruft, falls es keine gibt, die virtuelle Methode DefaultHandler auf.

Rein theoretisch sollte das auch mit einer ungültigen Instanz funktionieren, aber wie jeder Hack ist diese Angabe ohne Gewähr.

Gruß,
Sven
Sven
[Free Pascal Compiler Entwickler]
this post is printed on 100% recycled electrons
  Mit Zitat antworten Zitat
DSCHUCH

Registriert seit: 6. Jun 2007
Ort: Dresden
185 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#20

AW: Zugriff auf procedure und funktionen nicht instanziierter Klassen / Objekte

  Alt 13. Feb 2013, 22:55
erstmal danke für die antworten.

im Anhang habe ich mal ein bsp für einen StackTrace eines Fehlers angehangen, welchen ich derzeit provozieren kann, indem ich im start einer anwendung sofort ein Terminate einbringe (mittels timer, ich bin zufällig auf den effekt gestossen). Offensichtlich wird hier die hälfte der anwendung freigegeben, dann eine Message bearbeitet (wm_killfocus). Die Komponenten dürften bekannt sein, sodass vermutungen wie Spagetticode ausgeschlossen werden können. (DevExpress)

Wie man sieht: keine einzige Zeile eigener Quellcode. (oder eben schon entladen)

Ich habe jetzt mal grob die DevExpress quellen überflogen (eigentlich keine Zeit diese tage für solche Spielereien) und darin enthalten sind mehrere globale VariablenInstanzen, etc pp. da der Stacktrace durchklappert bis zum ersten Zugriff auf ein Klassenfeld, kann ich jetzt rätselraten, ob die vorherigen objekte nun instanziiert sind, oder der code zufällig so aufgebaut ist, das bis zuletzt nicht auf felder zugegriffen wird.

Zitat:
FastMem *zeigt* dir den Fehler (steht auch im Beitrag) und der Optimierer (steht auch da) sorgt eben beim 'wegkürzen' von Code dafür, das der Fehler u.U. in einer anderen Stelle angezeigt wird.
hier reden wir aneinander vorbei, was es theortisch macht ist mir auch wieder klar, was es praktisch wirklich ändert ist die frage. ich weiß zB nicht, ob man mit diesen/irgendwelchen Tools die Speicher komplett ausnullen kann, wenn ein objekt freigegeben wird, sodas es halt nicht mehr zufällige zugriffe auf zufällig vorhandenen code gibt.

Zitat:
Dir fehlen entscheidende Grundlagen, um hier mitreden bzw. kritisieren zu können.
Richtig. Ich bin Anwendungsentwickler und mein Fokus liegt darauf, mit Unternehmen Prozesse zu entwerfen und diese in eine Softwarestruktur zu bringen. Es interessiert mich grundsätzlich auch nicht, wie der Compiler etwas macht und wie nicht, würde mich das interessieren, wäre ich "richtiger Softwareentwickler" geworden und ich habe auch keine Zeit mehr für diese Dinge.
Da man bei solchen Fehlern wie zB den oben von Entwicklern idR hört "da war irgendwas nicht instanziiiert" und "das ist nicht nachvollziehbar" (ist ja auch so, wir haben das bei paar Hunder Anwendern bei manchen paar mal die Woche (alle 2-3 Tage), bei teilweise 24*7 Betriebsdauer der Software {Verwaltungssoftware Unternehmenssteuerung}), beschäftige ich mich derzeit halt doch mal wieder mit solchen dingen, da ich eher sehe wie Anwender eine Software bedienen und somit teilweise besser Rückschlüsse auf technische Abläufe/Zusammenhänge ziehen kann. Es geht ja zB schon damit los, das es für viele Bediener nur Doppelclick gibt, einfach klick gibt es nicht.

(daher haben wir mit vielen manwochen aufwand alle Application.processmessages ersetzt, da liegen ordner auf der tastatur während es rechnet, es werden zufällige tasten gedrückt, zum schluß kilbert es, da die anwendung irgendwelche eingaben verarbeitet hat)

Letzendlich ist die Frage, wie man in solchen Fällen von zufälligen Fehlern, welche meist im Stacktrace auf Codezeilen verweisen die nicht mal in den eigenen Bibliotheken liegen ein Debugging/Eingrenzung vornimmt.

Zitat:
Dispatch ist in TObject deklariert und sucht sich an Hand der Nachrichtentabelle des Objekts die passend message Methode raus oder ruft, falls es keine gibt, die virtuelle Methode
muß ich nachlesen, wie sich die WinControls da registrieren/deregistrieren und ob es möglich ist, das hier noch eine komponente/methodenzeiger in der Nachrichtentabelle steht, welche nicht mehr existiert.
Miniaturansicht angehängter Grafiken
13-02-2013-23-01-35.jpg  

Geändert von DSCHUCH (13. Feb 2013 um 22:59 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:18 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