![]() |
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
ok, SirT, das leuchtet mir ein... ändert ein const da dran was? bzw. was SOLL ich ändern?
|
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
Zitat:
Nicht gaaaanz richtig ;) Die Adresse die auf die Variable im Stack zeigt, zeigt weiterhin nach Verlassen der Funktion auf den Stack. ABER die Daten auf diesem Stack werden durch nachfolgendem Code permanent mit neuen Daten überschrieben. Das bedeutet das bei dem dereferenzierten Aufruf (und TypCast klar) man Daten auf dem Stack als Einsprungadresse in eine Methode interpretiert die irgendwo hin aber nicht dahin wo sie es sollte, zeigt. Der Programcounter der CPU springt also an irgendeine Addresse im Addressraum des Speichers. Gruß Hagen |
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
hatte ich doch geschrieben das der zeiger dann auf was anderes zeigt (also auf andere daten). Aber das ist OT - zurück zum Thema.
@Luke: Du solltest das Event kopieren. Und da ein Event größer als ein einfacher Pointer ist musst du dafür speicher anfordern (mit new) und diesen dann in deine Liste hängen. |
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
ok, werd ich machen.
Mit einer typed TObjectList, wie es sie in der Codelib gibt, funzt die sache offenbar auch nciht - er hält das event in FList.Add(_item) für einen Methodenaufruf... EDIT: So?:
Delphi-Quellcode:
Das is aber n bisschen umständlich, scheint mir... und was ist jetzt mit dem const? hat das irgendeinen einfluss auf irgendwas?
function TFormPanel.AddOnMouseMove(const Event: TMouseMoveEvent): Integer;
var CopyEvent: Pointer; begin CopyEvent := GetMemory(sizeof(TMouseMoveEvent)); CopyMemory(CopyEvent,@Event, sizeof(TMouseMoveEvent)); Result := MouseMoveEvents.Add(CopyEvent); end; Und vor allem: Das löst nicht das ursprungsproblem... |
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
Die Alternative wäre ein dynamisches Array, du mußt es ja nicht unbedingt in 1er-Schritten vergrößern. Damit reduzierst du aber den Verwaltungsaufwand beim Anfordern/Freigeben der Elemente.
Gruß Hawkeye |
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
Jaaa... und was ist jetzt mir meiner anfänglichen Frage? :wall:
Die existiert immer noch, denn fakt ist, wenn ich auf MouseMoveList.Count zugreife, gibt es eine AV... :cry: EDIT: nur zur auffrischung:
Delphi-Quellcode:
So adde ich ein Event zur Liste - stimmt das jetzt so?
function TPanelManager.AddOnMouseMove(const Event: TMouseMoveEvent): Integer;
var CopyEvent: Pointer; begin CopyEvent := GetMemory(sizeof(TMouseMoveEvent)); CopyMemory(CopyEvent,@Event, sizeof(TMouseMoveEvent)); Result := MouseMoveEvents.Add(CopyEvent); end; Und hier ist der schadcode:
Delphi-Quellcode:
Wos knallt hab ich hoffentlich fett genug markiert...
procedure TPanelManager.PanelMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer); var ListEvent: Pointer; xy: TFormPanel; c: TControl; i: Integer; begin xy := self; c := xy.GetElement; if xy.MouseMoveEvents.Count > 0 then //<<-- KNALLT HIER for i := 0 to xy.MouseMoveEvents.Count-1 do if Assigned(xy.MouseMoveEvents[i]) then TMouseMoveEvent(xy.MouseMoveEvents[i]^)(Sender, Shift, X, Y); end; EDIT: Den TPanelManager bekommt die Anwendung nur einmal in die Hand, dabei wird er in einen InterfaceManager created, der von da an das Interface bereitstellt. Das PanelMouseMove und die TList SOLLTEN aber davon doch absolut unbeeinflusst bleiben, es funktioniert ja offenbar auch der self-pointer - obwohl ich das einmal überprüfen sollte. Kann es denn sein, dass mir da irgendwelche Adressen/Instanzen verschütt gehen? |
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
Ok, du erzeugst deine TList's nur im Constructor und zerstörst sie nur im Destructor vom TPanelManager, an keiner anderen Stelle im Source, richtig ?
Dann ändere in deinem Destructor vom TPanelManager das Freigeben der Listen so ab das du FreeAndNil() dafür benutzt. Wichtig ist nur das du deine TList Felder auf NIL setzt. Jetzt debuggst du nochmal und prüfst Self.MouseMoveEvents <> nil ab. Ich vermute nämlich das du durch das Mixen von Interfaces und Objecten konzeptionell durcheinander kommst und das dein TPanelManager Object beim Aufruf von OnMouseMove() irgendwie zerstört wurde. Auf alle Fälle wäre das die einzigste Erklärung für einen logischen Programmierfehler, mit deinem vorgstellten wenigen Sourcen, die mir einfällt. Die wesentlich schlechtere Vermutung wäre das du tatsächlich mit wildem TypCasting Spiecherdaten überschreibst, das liegt aber dann eher am Programmierstil ansich. Ach und nochwas: Deine Zählschleife "for I := 0 to Liste.Count -1" ändere diese in eine downto Schleife ab. Immerhin rufst du eine Ereignissmethode auf und diese könnte sich ja exakt in ihrem Aufruf beim TPanelManager deinstallieren, also aus der TList selber entfernen. Das führt dann in deiner Schleife zum nächsten Crash. Und nochwas: Statt die Events in TLists zu speichern, baue dir lieber was eigenes. Entweder ein dynamisches Array of TMethod, was ich am sinnvollsten erachte oder eigene Records die verlinkt untereinander sind (verlinkte Liste) oder eben ein eigenes TList Object. Wichtig ist nur das du dann OHNE Zeiger, Speicherkopierungen etc.pp. auskommen wirst und mit simplem PASCAL Zuweisungen arbeiten kannst. Das reduziert enorm die Fehleranfälligkeit im Programcode gegen logische Programmierfehler. Der Fehler mit der Referenzierung des Events das auf dem Stack liegt IST defakto ein logischer Programmierfehler, du warst dir garnicht im Klaren was du da gemacht hast. Ergo ist es besser auf simple Standard-Konstrukte des PASCALs zurückzugreifen und eben Zeigerarithmetiken, TypCast und mischen von Objekten und Interfaces zu verzichten. Ein beliebiges Event kannst du so sicher casten:
Delphi-Quellcode:
Gruß Hagen
procedure XYZ(const Event: TMouseMoveEvent);
var MyEvent: TMethod; begin MyEvent.Data := TMethod(Event).Data; // <- Self des Eigners des Events aud den Code zeigt MyEvent.Code := TMethod(Event).Code; // <- Code ist die Addresse der Methode des Eigners die aufgerufen werden soll. end; |
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
Danke negaH, endlich ein Lichtblick... ja, beim debuggen habe ich mich im debug-inspektor mal bis zu TInterfacedObject.FRefCount durchgeklickt - und der war 0?! Ich seh mir das mal an...
"wildes" rumgecaste hab ich jetzt eigentlich keins mehr. Aber ich werde mal eine TMethodList komplett selberbauen, dann habe ich auch die andauernde Unterschioedung zwischen TMouseEvent und TMouseMoveEvent weg. Zitat:
Erzeugt werden sie im Aufruf von TPanelManager.CreateObject, das sollte ich irgendwo schon gepostet haben. Und freigegeben... bis jetzt... noch nie... verdammt, ich muss off. ich schreib später weiter :roll: EDIT: Alsoooo.... Ich hatte zwischendurch Angst, dass der Konstruktor nicht aufgerufen wird, sondern der von einer Basisklasse... (glaube den Code kann ich zeigen)
Delphi-Quellcode:
So wird das erzeugt.... wird an //fraglicher stelle denn der richtige Konstruktor aufgerufen? override konnte ich ja nicht machen, da ist drunter wohl nur TObject.Create, und das ist nicht virtuell...
//Initialisierung:
with Toolbox.Categories.Add do begin Caption := 'Containers'; with Items.Add do begin Caption := 'Panel'; Data := Pointer(PageManager.Supplier.AddClass(TFormPanel)); end; end; function TFormElementSupplier.AddClass(EClass: TFormElementClass): Integer; begin if not Supports(EClass,IID_IFormElement) then Raise EElementNotMatching.Create('This class does not support IFormElement interface!'); Result := Classes.Add(EClass); //TClassList end; function TFormElementSupplier.Instantiate(EClassIndex: Integer): IFormElement; var EClass: TFormElementClass; Element: TInterfacedObject; ElementIndex: Integer; begin EClass := TFormElementClass(Classes[EClassIndex]); Element := EClass.Create as TInterfacedObject; //fragliche Stelle ElementIndex := Elements.Add(Element); Result := Element as IFormElement; end; kurz das grundgerüst meines TPanelManager:
Delphi-Quellcode:
also ich denke mal, da wird auf jeden fall TObject.Create aufgerufen. Wäre es da nicht am praktikabelsten, eine Init-Prozedur ins Interface zu packen, die ich im Supplier aufrufe?
type
TPanelManager = class(TInterfacedObject, IFormElement); //IFormElement *implementier* constructor Create; //override; // geht nicht end; |
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
Zitat:
Stop, die Unterschiede zwischen diesen beiden Event-Typen liegen wahrscheinlich in deren Parametern. Sie sind also eben NICHT gleich und sie in einer einzigsten Liste zu speichern ist unsinnig. Denn beim Aufruf dieser Events aus der List musst du sie ja so casten das sie die korrekte Parametersignatur aufweisen, ansonsten kracht es gewaltig. Gruß Hagen |
Re: self kaputt? Listen-Initialisierung wegoptimiert? sonsti
:lol:
Na klar, denkst du ich bin lebensmüde? Ich sprache ja auch von TMethodList ;) (ich hab übrigens oben editiert.) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:11 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