Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Zugriffsverletzung beim TObjectDictionary.Add (https://www.delphipraxis.net/202195-zugriffsverletzung-beim-tobjectdictionary-add.html)

haentschman 8. Okt 2019 15:23

Zugriffsverletzung beim TObjectDictionary.Add
 
Hallöle...:P
Ich verstehe die Welt nicht mehr...:roll:

Delphi-Quellcode:
TUserRoleRightDict = TObjectDictionary<Integer, TUserRoleRight>;
...
UserRight := TUserRoleRight.Create;
UserRight.RightID := StrToInt(ContentList[0]);
...
FModifiedUserRole.RoleRightList.Add(UserRight);
FModifiedUserRole.RoleRightDict.Add(UserRight.RightID, UserRight);
Zitat:

...
exception message : Zugriffsverletzung bei Adresse 0167C71D in Modul '.exe'. Lesen von Adresse 00000000.
...
main thread ($2f88):
0167c71d +015 .exe SEAM.Classes.Data 6239 +4 {System.Generics.Collections}TDictionary<System.In teger,Classes.Data.TUserRoleRight>.Hash
0167cefb +02b .exe SEAM.Classes.Data 6347 +4 {System.Generics.Collections}TDictionary<System.In teger,.Classes.Data.TUserRoleRight>.Add
0368b635 +211 .exe Form.UserManager.Logic 329 +28 CreateNewRole
0368b6c0 +008 .exe Form.UserManager.Logic 334 +1 TUserManager.UserRoleAdd
0368fc26 +082 .exe Form.UserManager 1079 +7 TfoUserManager.gtvUserRoleNavigatorButtonsButtonCl ick
...
PS: Das TObjectDictionary ist instanziert. Allerdings ohne Objektfreigabe. Die Freigabe wird über eine sortierte Liste mit diesen Objekten realisiert. Im Prinzip enthällt das Dict die Objekte nur besser zum Suchen.
PS: Die Liste enthällt das korrekte Objekt.

Danke für Infos...:wink:

Stevie 8. Okt 2019 15:36

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Ich tipp mal auf nen falschen Konstruktoraufruf durch die ganzen Overloads beim TDictionary, so dass FComparer nil ist. :glaskugel:
Was sonst soll ne AV beim Lesen von Adresse 00000000 in der Methode Hash verursachen :gruebel:

Neutral General 8. Okt 2019 15:37

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
RoleRightDict.Create, statt RoleRightDict := TUserRoleRightDict.Create?

Zeig uns doch mal den Code wo das Dictionary erstellt wird.

haentschman 8. Okt 2019 15:42

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Bitteschön...:P
Delphi-Quellcode:
FRoleRightDict := TUserRoleRightDict.Create; // Dict ohne Freigabe (sortierte Liste RoleRightList)
FRoleRightList := TUserRoleRightList.Create; // List gibt Objekte frei
...
FRoleRightDict := TUserRoleRightDict.Create([doOwnsValues]); // gleicher Fehler
FRoleRightList := TUserRoleRightList.Create(False);
Wer meinen dusslichen Fehler findet...dem gebe ich ein :cheers: aus...

Nachtrag: FComparer ist nil. :shock:

Stevie 8. Okt 2019 16:01

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
- Stoppunkt nach dem Create und schauen, ob FRoleRightDict.FComparer assigned ist.
- Schauen, ob es nicht aus Versehen irgendwo freigegeben wird bevor der Add Aufruf passiert.

P.S. Ich glaub, ich mach mal für die Forentage 2020 einen "Fehleranalyse 101" Vortrag 8-)

haentschman 8. Okt 2019 16:22

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Ich glaub, ich mach mal für die Forentage 2020 einen "Fehleranalyse 101" Vortrag
...Danke für die aufbauenden Worte. :? Kannst du dir vorstellen, daß ich für das Debuggen von "Bibliotheken" keinen Nerv/Zeit habe?

Ich verwende Dictionaries ständig. Einen Comparer habe ich noch nie benutzt. Ich erstelle die Instanz wie immer meistens mit [doOwnsValues].

Danke...

Nachtrag:

* Nach dem Create ist der Comparer Assigned (Pointer($3BFEF6C) as {System.Generics.Defaults}IEqualityComparer<System .Integer>)
* vor dem Add ist der Comparer Assigned (nil)
-> dazwischen passiert mit dem Dict nix. Das Dict wird erzeugt und dann beschrieben. :?

Eine Idee habe ich noch...aber erst morgen früh.

Stevie 8. Okt 2019 16:40

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Zitat von haentschman (Beitrag 1449303)
Zitat:

Ich glaub, ich mach mal für die Forentage 2020 einen "Fehleranalyse 101" Vortrag
...Danke für die aufbauenden Worte. :? Kannst du dir vorstellen, daß ich für das Debuggen von "Bibliotheken" keinen Nerv/Zeit habe?

Ich verwende Dictionaries ständig. Einen Comparer habe ich noch nie benutzt. Ich erstelle die Instanz wie immer meistens mit [doOwnsValues].

Danke...

Hilfe zu leisten kostet natürlich keine Zeit...

Es geht nur darum, dass wenn bestimmte grundlegenden Dinge schon vorab passiert sind (und das ist nun keineswegs nur auf dich und diesen Fall bezogen) man entweder schon selbst drauf kommt oder es anderen erleichtert, Hilfe zu leisten. Das ist glaube ich, im Interesse aller.

Ist wie mit dem Fisch geben oder Angeln beibringen. Klar, wenn man keine Lust oder Zeit auf Angeln hat, kann man auch andere nach nem Fisch fragen (oder man kauft ihn im Supermarkt) :roll:

Punkt ist, dass man keinen comparer angeben muss, der wird intern gebaut/bezogen. Wenn der also plötzlich nil ist, kann es sich nur um Vorzeitiges Freigeben des Dictionaries handeln oder was ich eher für unwahrscheinlich halte Speicherüberschreiben dieses Objekts durch eine andere Stelle.

Der schöne Günther 8. Okt 2019 18:20

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Und was ist "TSEAMUserRoleRightDict"? Ist das immer noch ein Alias? Oder eine eigene Unterklasse welche z.B. nur "inherited" oder "inherited Create" im Konstruktor sagt?

Ein Codeschnippsel zum Nachstellen wäre echt super-hilfreich.

haentschman 8. Okt 2019 19:00

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
TSEAMUserRoleRightDict war ein Tippfehler.
Korrekt wäre wie in den Codeschnippseln TUserRoleRightDict.

Danke...

haentschman 9. Okt 2019 05:48

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Moin...8-)
Zitat:

Eine Idee habe ich noch...aber erst morgen früh.
...Fazit: Eine Objektkopie mit Marshal/UnMarshal nimmt den Comparer nicht mit. :?

Danke für eure Hilfe.

Incocnito 9. Okt 2019 07:09

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Objektkopie?
Hat das Objekt ein "Assign", oder wie genau?
Delphi-Quellcode:
StringList1 := TStringList.Create();
StringList2 := StringList1;
StringList1.Free();
StringList2.Add('Something'); // <- Alles Kaputt, so geht das natürlich nicht!
Für den höchst unwahrscheinlichen Fall, dass du das meintest.

haentschman 9. Okt 2019 07:24

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Hat das Objekt ein "Assign", oder wie genau?
Normal macht man das klassisch mit Assign. Meine "Datenobjekte" haben auch Listen mit Objekten. Deshalb benutze ich gern folgendes:
Delphi-Quellcode:
class function TToolsJson.ObjectCopyJson(Value: TObject): TObject;
var
  MarshalObj: TJSONMarshal;
  UnMarshalObj: TJSONUnMarshal;
  JSONValue: TJSONValue;
begin
  Result := nil;
  MarshalObj := TJSONMarshal.Create;
  try
    UnMarshalObj := TJSONUnMarshal.Create;
    try
      JSONValue := MarshalObj.Marshal(Value);
      try
        if Assigned(JSONValue) then
          Result := UnMarshalObj.Unmarshal(JSONValue);
      finally
        JSONValue.Free;
      end;
    finally
      UnMarshalObj.Free;
    end;
  finally
    MarshalObj.Free;
  end;
end;
...nur leider funktioniert das nicht immer. :( Wie man an dem o.g. Fehler erkennen kann, werden Dictioniaries nicht wieder richtig erzeugt. Ich habe deshalb wieder nur auf Liste umgestellt.

Der schöne Günther 9. Okt 2019 09:00

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Zitat von haentschman (Beitrag 1449324)
Moin...8-)
Zitat:

Eine Idee habe ich noch...aber erst morgen früh.
...Fazit: Eine Objektkopie mit Maschal/UnMarschal nimmt den Comparer nicht mit. :?

Ja, leider.
Siehe auch hier:
https://stackoverflow.com/a/49636496/2298252

Incocnito 9. Okt 2019 15:32

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Sowas geht auch nur ansatzweise?
Ich hätte gesagt, da es sich ja nur um den Typen "TObject" handelt,
weiß Delphi eh nicht, was zu tun ist und stellt nur irgendeinen Mist her.
Ich bin total verwirrt! Das ist für mich schon quasi EDV-Magie! :oops:

Uwe Raabe 9. Okt 2019 15:39

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Zitat von Incocnito (Beitrag 1449381)
Das ist für mich schon quasi EDV-Magie!

Das dazugehörige Zauberwort heißt RTTI.

haentschman 10. Okt 2019 05:51

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Moin...:P
Zitat:

Ich hätte gesagt, da es sich ja nur um den Typen "TObject" handelt,
Du bekommst schon das raus was du reinsteckst. Du mußt nur das Ergebnis TObject auf deinen Typ casten.
Delphi-Quellcode:
BlubbCopy := TBlubb(TTools.ObjectCopy(Blubb));

generic 10. Okt 2019 10:01

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Zitat von haentschman (Beitrag 1449301)
Bitteschön...:P
Delphi-Quellcode:
FRoleRightDict := TUserRoleRightDict.Create([doOwnsValues]); // gleicher Fehler

Wenn ich mir die Exception und den Stacktrace anschaue, dann glaube ich eher das es am KEY liegt.
Ähnlich wie bei den Values, kann auch der KEY owned werden.

haentschman 10. Okt 2019 10:09

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Wenn ich mir die Exception und den Stacktrace anschaue, dann glaube ich eher das es am KEY liegt.
Dem widerspricht die fast tägliche Benutzung / Implementierung eines Dictionaries. :wink: Die diesem Falle war aber eine Objektkopie des Datenobjektes mit enthaltenem Dictionary verantwortlich. Mit der Kopie ist der FComparer intern nicht instanziert worden. :?

Danke...:wink:

Uwe Raabe 10. Okt 2019 11:40

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Zitat von haentschman (Beitrag 1449421)
diesem Falle war aber eine Objektkopie des Datenobjektes mit enthaltenem Dictionary verantwortlich. Mit der Kopie ist der FComparer intern nicht instanziert worden.

Das liegt vermutlich daran, daß nicht der gewünschte Construktor von TDictionary aufgerufen wurde, sondern der von TObject, weil UnMarshal nach einem parameterlosen Constructor sucht. Und Interface-Felder werden offenbar nicht serialisiert.

haentschman 10. Okt 2019 11:44

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Und Interface-Felder werden offenbar nicht serialisiert.
...genau. :P

Stevie 14. Okt 2019 09:48

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Eine Objektkopie mit Marshal/UnMarshal nimmt den Comparer nicht mit.
Unwesentliches Detail, was bisher fehlte :roll:

Lösung kann auch so aussehen:

Delphi-Quellcode:
TUserRoleRightDict = class(TObjectDictionary<Integer, TUserRoleRight>)
  constructor Create; overload;
end;

constructor TUserRoleRightDict.Create;
begin
  inherited Create;
end;
Dann ruft das JSON dings den richtigen ctor auf.

P.S. Das Problem wird übrigens auch bei TObjectList<T> passieren. Denn dann wird der parameterlose ctor von TList<T> aufgerufen und dann bleibt FOwnsObjects auf false. Nur als Hinweis, falls mal irgendwo massive Leaks auftreten. :wink:

Uwe Raabe 14. Okt 2019 10:37

AW: Zugriffsverletzung beim TObjectDictionary.Add
 
Zitat:

Zitat von Stevie (Beitrag 1449577)
P.S. Das Problem wird übrigens auch bei TObjectList<T> passieren. Denn dann wird der parameterlose ctor von TList<T> auf und dann bleibt FOwnsObjects auf false. Nur als Hinweis, falls mal irgendwo massive Leaks auftreten. :wink:

:thumb:


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