Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   BoolToStr wirft Access Violation (https://www.delphipraxis.net/169047-booltostr-wirft-access-violation.html)

himitsu 26. Jun 2012 16:19

AW: BoolToStr wirft Access Violation
 
Zitat:

Zitat von Bummi (Beitrag 1172534)
Move mit Strings in Records gehen nicht.

Genauer bei "Long-Strings" und WideString.
ShortString und statische Char-Arrays gehn.

Genauso wie es bei Interfaces, Variants und dynamischen Arrays auch nicht geht, bzw. nicht ohne Beachteung gewisser Dinge, bei deren automatischen Speicherwerwaltung.


In der Unit System gibt es eine Abteilung "Compiler helper for initializing/finalizing variable" mit netten Funktionen.
New
Dispose
Initialize
InitializeArray
InitializeRecord
Finalize
FinalizeArray
FinalizeRecord
CopyArray
CopyRecord

Welche Delphi intern verwendet und die man notfalls selber verwenden könnte, aber dennoch sollte man ein bissl Ahnung davon haben, wie z.B. die Speicherverwaldung und Referenzzählung arbeiten.

Ansonsten: Finger weg, von direkten Speichermanipulationen. (Pointer, Move und Co.)

Blup 27. Jun 2012 11:35

AW: BoolToStr wirft Access Violation
 
Zitat:

Zitat von hyype (Beitrag 1172531)
Delphi-Quellcode:
  move(MyArrayOfMyRecord[i], MyArrayOfMyRecord[i-1], (length(MyArrayOfRecord)-i) * sizeof(MyRecord));
  setlength(MyArrayOfMyRecord, length(MyArrayOfMyRecord)-1);
was ist das Ergebnis? Kauderwelsch oder? ^^
Weil er kann ja die Größe meines Records nicht anhand des Typs bestimmen, weil weder Länge des Strings, noch Länge des StringArrays fest sind.
Er könnte höchstens die Größe eines ganz bestimmten Objektes dieses Typs ermitteln, was bedeuten würde, ich müsste die Summe an Bytes, die er moven soll, selbst bestimmen aus der Summe der Größe aller zu verschiebenden Elemente anstatt die Größe des Records mit der Anzahl zu multiplizieren, richtig?
Ließe sich dieses Problem umgehen, wenn man aus dem Record eine Klasse machen würde?

Die Grösse der Strings spielt keine Rolle, im Record sind nur Zeiger auf die Strings abgelegt.
Zeiger belegen immer 4 Byte, deshalb sind alle Elemente des Arrays gleich groß.
Das Element[i] wird mit Move überschrieben, ohne das die Speicherverwaltung der dort referenzierten Strings etwas mitbekommt. Diese Strings werden nie mehr freigegeben.
Kann man so umgehen:
Delphi-Quellcode:
Finalize(MyArrayOfMyRecord[i]);
move(MyArrayOfMyRecord[i], MyArrayOfMyRecord[i - 1], (Length(MyArrayOfRecord) - i) * Sizeof(MyRecord));
Nach dem Move verweist das letzte und das vorletzte Element auf die selben Strings, diese wissen aber nichts von der zusätzlichen Referenz. Das anschließende SetLength löscht das letzte Element und verringert den Referenzzähler der Strings. Dadurch werden diese freigegeben obwohl ja noch ein Element darauf verweist.
Kann man so umgehen:
Delphi-Quellcode:
FillChar(MyArrayOfMyRecord[Length(MyArrayOfRecord) - 1], Sizeof(MyRecord), #0);
SetLength(MyArrayOfMyRecord, Length(MyArrayOfRecord) - 1);

hyype 29. Jun 2012 13:04

AW: BoolToStr wirft Access Violation
 
Zusammenfassend lässt sich also sagen:

Delphi-Quellcode:
move(MyArrayOfMyRecord[i], MyArrayOfMyRecord[i-1], (length(MyArrayOfRecord)-i) * sizeof(MyRecord));
setlength(MyArrayOfMyRecord, length(MyArrayOfMyRecord)-1);
wird zu

Delphi-Quellcode:
Finalize(MyArrayOfMyRecord[i]);
move(MyArrayOfMyRecord[i], MyArrayOfMyRecord[i-1], (length(MyArrayOfRecord)-i) * sizeof(MyRecord));
FillChar(MyArrayOfMyRecord[Length(MyArrayOfRecord) - 1], Sizeof(MyRecord), #0);
setlength(MyArrayOfMyRecord, length(MyArrayOfMyRecord)-1);


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:34 Uhr.
Seite 2 von 2     12   

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