在 Delphi 中,如何修复 64 位发布版本中 FreeAndNil 的访问冲突(当 64 位调试版本有效时)?

In Delphi, how to fix access violation on a FreeAndNil in 64-bit release build (when 64-bit debug build works)?

这是我的问题的一些简化代码上下文:

TSomeone = record
    FirstName: String;
    LastName: String;
    Picture: TGraphic;
end;

TSomeoneHelper = record helper for TSomeone
    public
        procedure Clear();
        procedure LoadFromFile(const Filename: String);
end;

procedure TSomeoneHelper.Clear();
begin
    Self.FirstName := '';
    Self.LastName:= '';

    try
        if Assigned(Self.Picture) then
            FreeAndNil(Self.Picture); // <---- Crash here in 64-bit release
    except
        Self.Picture := nil;
    end;
end;

通常有人会声明一个TSomeone变量,然后调用myVar.LoadFromFile('myfile.blah')来填充记录。在 LoadFromFile 过程中创建了一个 TJPEGImageTGraphic 后代),然后分配给 Picture.

因为我不在 class 中(record helper 中没有构造函数)我无法将 Picture 初始化为 nil。因为 FreeAndNil 崩溃。奇怪的是,在 32 位构建中,它似乎初始化为 nil,但在 64 位构建中它不是(它是 "Inaccessible value")。出于这个原因,我添加了 try except。但在 64 位版本中更奇怪的是,我遇到了 try except.

未捕获的访问冲突

总结一下:

我该怎么做才能解决这个问题?

它在构建类型和体系结构之间的工作方式不同这一事实纯属运气。这在任何地方都不起作用(OP 评论只是证实了我的想法)。

如果使用 Delphi 10.4+,则使用 Custom Managed Records 将(非托管)var 初始化为 nil,并且 Assigned() 调用不会造成访问冲突。

最后我只是重构了我的代码以使用 类 而不是记录。在构造函数中,我将 var 初始化为 nil。它更干净,可以与 any 版本的 Delphi.

一起使用