Ich schätze, mein Problem wird durch das Konzept verursacht, wie UnicodeStrings implementiert sind, aber ich kann dieses Problem nicht lösen.Lazarus/Delphi: UnicodeString in selbst zugewiesenen Datensatz-Datentyp verursacht Zugriffsverletzungen
Ich versuche, eine Verzeichnisstruktur auf Platte rekursiv zu scannen und eine Baumansicht zu erstellen, die alle Dateien und Unterordner anzeigen sollte. Außerdem möchte ich zusätzliche Informationen für jeden Baumknoten speichern. Das TTreeNode-Objekt hat zu diesem Zweck nur eine "Data" -Eigenschaft (Typ Pointer), also ordne ich Speicher manuell zu, speichere die Informationen und weise den zugewiesenen Zeiger meiner Dateneigenschaft zu. Alles scheint gut zu funktionieren, es sei denn, ich verwende ein UnicodeString-Feld innerhalb meines Datensatzes.
So, hier ist meine benutzerdefinierte Datensatzdefinition: mein Code für das Verzeichnis recusion
type
TFileInformation = record
AbsoluteFileName: UnicodeString;
FileSize: Int64;
FileAttributes: LongInt;
CreationTime, ModificationTime: TDateTime;
end;
Und hier ist:
const NO_ERROR = 0;
procedure ScanDirectory(Folder: UnicodeString; Node: TTreeNode);
var
Details: Pointer;
NewNode: TTreeNode;
SearchAttributes: LongInt;
SearchMask: UnicodeString;
SearchRecord: TUnicodeSearchRec;
begin
if (Folder <> '') and (Folder[Length(Folder)] <> DirectorySeparator) then begin
Folder += DirectorySeparator;
end;
SearchMask := Folder + '*'{$IFDEF WINDOWS} + '.*'{$ENDIF};
SearchAttributes := faReadOnly or faHidden or faSysFile or faDirectory or faArchive or faSymLink;
if FindFirst(SearchMask, SearchAttributes, SearchRecord) = NO_ERROR then begin
repeat
if ((SearchRecord.Attr and faDirectory) <> faDirectory) or
((SearchRecord.Name <> '.') and (SearchRecord.Name <> '..')) then begin
Details := MemAlloc(SizeOf(TFileInformation));
//TFileInformation(Details^).AbsoluteFileName := Folder + SearchRecord.Name;
TFileInformation(Details^).FileAttributes := SearchRecord.Attr;
TFileInformation(Details^).FileSize := SearchRecord.Size;
TFileInformation(Details^).CreationTime := SearchRecord.Time;
//TFileInformation(Details^).ModificationTime := -1;
if Node = nil then begin
NewNode := self.trvOrigin.Items.AddNode(nil, nil, ansistring(SearchRecord.Name), Details, naAdd);
end else begin
NewNode := self.trvOrigin.Items.AddNode(nil, Node, ansistring(SearchRecord.Name), Details, naAddChild);
end;
if (SearchRecord.Attr and (faDirectory or faSymLink)) = faDirectory then begin
// only recurse folders which are NOT SymLink:
ScanDirectory(Folder + SearchRecord.Name, NewNode);
end;
end;
until FindNext(SearchRecord) <> NO_ERROR;
end;
FindClose(SearchRecord);
end;
Wenn ich die Zeile mit .AbsoluteFileName :=
Kommentar-, ich Zugriffsverletzung erhalten (SIGSEGV-Ausnahme in Unix). Ich benutze derzeit Lazarus in objfpc
Modus auf Debian Linux, aber ich denke, es ist das gleiche mit Delphi unter Windows. Der Treeview.Data-Eigenschaftswert wird in der Variablen "Details" in meinem Beispielcode gespeichert. Self.trvOrigin ist mein Treeview-Steuerelement.
Woher kommt die Funktion 'MemAlloc'? Wie ich mich erinnere, ist es Windows-spezifische Funktion. Kann es nur in der "FreeVision" -Speichereinheit finden (zusätzlich zur "Windows" -Einheit) ... – Abelisto
Ich benutze die Speichereinheit, die in Lazarus enthalten ist. –
Wäre es nicht besser, einfach eine abgeleitete Klasse von TTreeNode zu erstellen, die zusätzliche Felder enthalten würde, die Sie benötigen. Auf diese Weise müssen Sie sich keine Gedanken darüber machen, wie Sie Speicher für zusätzliche Informationen zuweisen und freigeben können. Das einzige Szenario bei der Verwendung der Eigenschaft Data wäre besser, wenn mehrere Baumknoten dieselben zusätzlichen Informationen enthalten oder wenn diese zusätzlichen Informationen separat verwaltet werden. – SilverWarior