Je suppose que mon problème est dû au concept de la façon dont UnicodeStrings est implémenté, mais je ne peux pas résoudre ce problème.Lazarus/Delphi: UnicodeString dans le type de données d'enregistrement auto-attribué provoque des violations d'accès
J'essaye de scanner une arborescence de répertoires sur le disque de façon récursive et de construire une arborescence qui devrait montrer tous les fichiers et sous-dossiers. De plus, je veux stocker des informations supplémentaires pour chaque nœud d'arbre. L'objet TTreeNode a uniquement une propriété "Data" (type Pointer) à cet effet, donc j'alloue la mémoire manuellement, stocke les informations et affecte le pointeur alloué à ma propriété de données. Tout semble fonctionner correctement à moins d'inclure l'utilisation d'un champ UnicodeString dans mon enregistrement de données.
Donc, voici ma définition d'enregistrement de données personnalisées:
type
TFileInformation = record
AbsoluteFileName: UnicodeString;
FileSize: Int64;
FileAttributes: LongInt;
CreationTime, ModificationTime: TDateTime;
end;
Et voici mon code pour le répertoire recusion:
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;
Quand je décommenter la ligne contenant .AbsoluteFileName :=
, je reçois une violation d'accès (SIGSEGV-Exception sous Unix). J'utilise actuellement Lazarus en mode objfpc
sur Debian Linux, mais je suppose que c'est la même chose avec Delphi sous Windows. La valeur de la propriété Treeview.Data est stockée dans la variable "Details" dans mon exemple de code, self.trvOrigin est mon contrôle treeview.
D'où vient la fonction 'MemAlloc'? Comme je me souviens, c'est la fonction spécifique de Windows. Peut le trouver uniquement dans l'unité 'Memory' de' FreeVision' (en plus de l'unité 'Windows') ... – Abelisto
J'utilise l'unité de mémoire incluse dans Lazarus. –
Ne serait-il pas préférable de simplement créer une classe dérivée à partir de TTreeNode qui contiendrait des champs supplémentaires dont vous avez besoin. De cette façon, vous n'aurez pas à vous soucier d'assigner et de libérer de la mémoire pour des informations supplémentaires par vous-même. Le seul scénario lors de l'utilisation de la propriété Data serait préférable lorsque plusieurs des nœuds d'arborescence contiendraient les mêmes informations supplémentaires ou si ces informations supplémentaires sont conservées séparément. – SilverWarior