Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Access Violation und ich versteh nicht warum....
catweasel - So 21.04.13 00:17
Titel: Access Violation und ich versteh nicht warum....
Hi,
Ich habe hier ein kleines Problem. Es gibt eine Liste mit Objekten und sollen in einen FileStream geschrieben und wieder gelsen werden.
Beim Schreiben (scheint) alles soweit zu funktionieren. Und bei dem zugriff auf die Objekte geht auch alles glatt.
Nur beim Laden geht es nicht. :(
Beim debuggen triggert die Access Violation schon beim Zufriff auf die LoadFromStream Routine...
Ich kann einfach den Fhler nicht finden. Alle Objektinstanzen sollten eigentlich ordentlich erstellt sein. Der Zugriff auf zur Laufzeit erstellte Instazen klappt ja auch problemlos.
Um den Fehler zu reproduzieren: Ein paar neue Materialien erstellen und dann versuchen das MAterial Set zu speichern und wieder zu laden.
Warum scheitert der Zugriff auf FDisffuse.LoadFromStream()? :?
Ein ähnliches Problem gibt es auch bei den Laden/Speichern Routinen der T3DSceneClass. Erstellt einfach mal ein Objekt und versucht die Szene zu speichern / laden.
Wenn man versucht eine neue Kamera hinzu zu fügen... das Gleiche. Eine AV.. beim Zugriff auf FFOV. Warum :?:
Hinweis: Die neuen Objekte werden nur mit Dummy Daten gefüllt. Auch ansonsten ist das Programm natürlich noch an allen Fronten Baustelle.
Nur bringen mich diese Access Violation fast um den Verstand. Das ist seht hinderlich beim weitermachen....:cry:
Wäre echt super wenn mir jemand weiterhelfen könnte. :)
Cheers,
Catweasel
jaenicke - So 21.04.13 09:13
Das liegt an deiner Stringspeicherung in TStringValueClass. Du musst das erste Zeichen als Bufferstart übergeben, nicht den String-Pointer, der auf den String zeigt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| var Size : longint; begin AStream.Read(Size,SizeOf(Size)); setlength(FText,Size); AStream.Read(FText[1],Size); end;
procedure TStringValueClass.SaveToStream(AStream: TFileStream); var Size : longint; begin Size := length(FText); AStream.Write(Size,SizeOf(Size)); AStream.Write(FText[1],Size); |
Bei der Gelegenheit würde ich auch gleich AnsiString nehmen, damit dein Dateiformat auch lesbar bleibt, wenn dein Projekt mit Delphi 2009 oder höher kompiliert wird. Und wenn du es ganz optimal willst, speichere den String als UTF8, dann geht auch Unicode ab Delphi 2009 und es bleibt kompatibel:
Delphi-Quelltext
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: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| function LoadStringFromStream(AStream: TStream): String; var ResultString: AnsiString; StringSize: Integer; begin Result := ''; if AStream.Size - AStream.Position < SizeOf(StringSize) then Exit; AStream.ReadBuffer(StringSize, SizeOf(StringSize)); SetLength(ResultString, StringSize); if AStream.Size - AStream.Position < StringSize then Exit; AStream.ReadBuffer(Pointer(ResultString)^, StringSize); {$ifdef UNICODE} Result := Utf8ToString(ResultString); {$else} Result := Utf8Decode(ResultString); {$endif} end;
procedure SaveStringToStream(AStream: TStream; AString: String); var StringSize: Integer; StringToSave: AnsiString; begin StringToSave := Utf8Encode(AString); StringSize := Length(StringToSave); AStream.WriteBuffer(StringSize, SizeOf(StringSize)); AStream.WriteBuffer(Pointer(StringToSave)^, StringSize); end;
procedure TStringValueClass.LoadFromStream(AStream: TFileStream); begin FText := LoadStringFromStream(AStream); end;
procedure TStringValueClass.SaveToStream(AStream: TFileStream); begin SaveStringToStream(AStream, FText); end; |
catweasel - So 21.04.13 10:37
jaenicke hat folgendes geschrieben : |
Das liegt an deiner Stringspeicherung in TStringValueClass. Du musst das erste Zeichen als Bufferstart übergeben, nicht den String-Pointer, der auf den String zeigt: |
Aua. :oops: Ich bin mal wieder darauf reingefallen das strings in Delphi nur wegen der Compiler Magic so bequem sind. Natürlich muss das eine Zeigerreferenz sein. :roll:
Vielen Dank für die schnelle Hilfe :)
An die Sache mit utf8 hatte ich noch garnicht gedacht... Danke für den Tip. Wird natürlich so umgesetzt ;)
Aaaaaber.. Ein kleines Problem gibts noch: Bei dem Versuch eine Kmera zu erstellen (wird weit und brei keine String Klasse verwendet).
D.h. dieser Fehler besteht weiterhin... :?
Sow wie ich das eingrenzen konnte schlägt es bei dem Zugriff auf FOVEdit.FloatValue1D (Unit UCameraDlg, Zeile 81) fehl.
Aber OriginEdit und DirectionEdit machen os ziemlich das selbe. Dort klappts... :?:
Cheers,
Catweasel
jaenicke - So 21.04.13 11:48
Woanders kommt bei mir kein Fehler. Und FastMM findet zwar einige Speicherlecks, weil Klassen nicht wieder freigegeben werden, aber keine anderen Speicherprobleme.
Was genau machst du bis der Fehler kommt? Und kommt er dann bei dir immer?
catweasel - So 21.04.13 13:17
jaenicke hat folgendes geschrieben : |
Woanders kommt bei mir kein Fehler. Und FastMM findet zwar einige Speicherlecks, weil Klassen nicht wieder freigegeben werden, aber keine anderen Speicherprobleme.
Was genau machst du bis der Fehler kommt? Und kommt er dann bei dir immer? |
Ja, um das korekte Freigeben hab ich mich noch nicht gekümmert. DAs Programm leckt noch wie ein Sieb.
Der Fehler tritt bei mir auf sobald ich eine Kamera erstellen will. D.h: Anwendung starten. Auf Camera > New klicken.
Im Dialog was eintragen (oder Null Werte so lassen, macht keinen Unterschied) und dann auf Create klicken.
Dan kommt der Error.
Wenn ich in UCameraDlg Zeile 81 testhalber abändere in:
Result.FOV.Value := 0; dann klappt es.
Noch merkwürdiger: Ich habe mal probehalber das FOVEdit.Free; aus dem destructor entfernt. Dann funktioniert es ebenfalls :shock: ..
Igendwas muss da mit dem FOVEdit Objekt nicht stimmen. Die AV kommt also wenn entweder auf das Objekt zugegriffen wird, oder wenn es im destructor freigegeben wird.
Fast so als fände der Zugriff erst nach dem Zerstören es Elements statt. Der RenderSettings Dialog funktioniert auch klaglos. Ebenso die OriginEdit und ScaleEdit Objekte im Camera Dialog..
Der Fehler kommt jedesmal. Ich dachte schon das da irgendwo vielleicht ne race condition entsteht, aber das ist bei der Art wie der Dialog erzeugt wird (Tmainform.newcammnuClick in UMain) eigentlich nicht möglich....
Cheers,
Catweasel
jaenicke - So 21.04.13 17:18
catweasel hat folgendes geschrieben : |
Wenn ich in UCameraDlg Zeile 81 testhalber abändere in: Result.FOV.Value := 0; dann klappt es |
Da ich es nicht reproduzieren kann:
Was passiert, wenn du auf diese Zeile einen Haltepunkt setzt und den Wert von Self prüfst? Ist der vielleicht nil?
catweasel - So 21.04.13 17:59
jaenicke hat folgendes geschrieben : |
catweasel hat folgendes geschrieben : | Wenn ich in UCameraDlg Zeile 81 testhalber abändere in: Result.FOV.Value := 0; dann klappt es | Da ich es nicht reproduzieren kann:
Was passiert, wenn du auf diese Zeile einen Haltepunkt setzt und den Wert von Self prüfst? Ist der vielleicht nil? |
Alles sit soweit referenziert (FOVEdit und 'self' natürlich auch), bis auf FloatValue1D. Dort sagt mir der Tooltip beim debuggen: Access Violation.
Ich habe einmal mein Fraps abgestaubt und ein kleines Demovideo von dem Programmverhalten gemacht. Bin gerade dabei das hochzuladen (youtube). Ich hoffe das klappt. KAnn nur etwas dauern. Aber im Laufe des Abends wird der Upload wohl durch sein.
Ich poste hier dann den Link zum Video.
Cheers,
Catweasel
catweasel - So 21.04.13 19:05
catweasel hat folgendes geschrieben : |
Ich poste hier dann den Link zum Video. |
So.. Und hier isser :
http://www.youtube.com/watch?v=3ZzKyIWQ1kI
Ich hoffe man kann es etwas erkennen...
Tip: Den Sound abdrehen ;)
Cheers,
Catweasel
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!