Lazarus / Delphi:自分配记录数据类型中的UnicodeString导致访问冲突

时间:2016-07-02 11:51:19

标签: dynamic-memory-allocation lazarus unicode-string delphi

我想,我的问题是由UnicodeStrings如何实现的概念引起的,但我无法解决这个问题。

我试图以递归方式扫描磁盘上的目录树,并构建一个应显示所有文件和子文件夹的树视图。另外,我想为每个树节点存储其他信息。 TTreeNode对象只有一个"数据"为此目的的属性(类型指针),所以我手动分配内存,存储信息并将分配的指针分配给我的数据属性。除非我在数据记录中包含UnicodeString字段,否则一切似乎都能正常工作。

所以,这是我的自定义数据记录定义:

type
  TFileInformation = record
    AbsoluteFileName: UnicodeString;
    FileSize: Int64;
    FileAttributes: LongInt;
    CreationTime, ModificationTime: TDateTime;
  end;

这是我的目录记录代码:

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;

当我取消注释包含.AbsoluteFileName :=的行时,出现访问冲突(Unix中的SIGSEGV异常)。 我目前在Debian Linux上以objfpc模式使用Lazarus,但我想它与Windows上的Delphi相同。 Treeview.Data属性值存储在&#34; Details&#34;在我的示例代码中,self.trvOrigin是我的树视图控件。

1 个答案:

答案 0 :(得分:4)

分配Details记录时,未定义内存。

AbsoluteFileName是托管类型,必须在使用前正确初始化。 分配后需要清除内存:

FillChar(Details^, SizeOf(TFileInformation), #0);

作为替代方案,请将New(Details)Dispose(Details)结合使用。 他们将正确初始化/完成记录。

注意:Details必须是类型指针PFileInformation