gpt4 book ai didi

delphi - 在 Delphi 中使用 Default() 赋值来初始化记录变量是否安全?

转载 作者:行者123 更新时间:2023-12-02 09:28:04 24 4
gpt4 key购买 nike

将 Default(TMyRecord) 分配给 TMyRecord 的变量据说会在内部首先调用 Finalize,然后像 FillChar 一样将内存清零。例如,这已经在对以下问题的回答中说过,并且我确实测试了分配 Default() 确实会导致调用例如 System._FinalizeRecord

How to properly free records that contain various types in Delphi at once?

Difference between Initialize(), Default() and FillChar()

我的问题是,即使在 Delphi 没有自动调用它的情况下,初始化这样的记录总是安全的吗?对我来说,对未初始化的记录变量调用 Finalize 似乎没有意义。在初始化之前,必须假设内存包含随机垃圾。在本例中,我对托管类型特别感兴趣,它们是指向动态分配内存的指针,Finalize 例程应通过减少其引用计数等来完成这些类型。在许多情况下,Delphi 自动生成对 Initialize 的调用,以确保其托管类型保持托管状态。但并非总是如此。

这是一个说明问题案例的示例。正如下面的答案中所评论的,您不应该使用 GetMem 来分配包含这样的托管类型的记录,但我们假设有人这样做了,然后尝试使用 Default() 分配作为初始化

type
TMyRecord = record
s1, s2, s3 : String;
end;
PMyRecord = ^TMyRecord;

var
pr : PMyRecord;

begin
GetMem(pr, SizeOf(TMyRecord));
pr^ := Default(TMyRecord);
...

我故意使用 GetMem() 而不是 New(),因为据我所知,GetMem() 返回的内存不应该自动归零,并且编译器不应该插入对 Initialize 的自动调用。那么在这种情况下,使用默认分配来初始化记录不是不安全吗?

在 David 接受的答案中,他对记录类型使用了一种漂亮的 Clear 方法 How to properly free records that contain various types in Delphi at once?让我们添加一个

  TMyRecord = record
s1, s2, s3 : String;
procedure Clear;
end;
...
procedure TMyRecord.Clear;
begin
Self := Default(TMyRecord);
end;

现在,Clear 例程绝对无法知道记录是位于堆栈还是堆上,以及是否已对其调用了 Initialize。

最佳答案

GetMem(pr, SizeOf(TMyRecord));
pr^ := Default(TMyRecord);

上面的代码是错误的。但这与 Default() 的使用无关。考虑这段代码:

GetMem(pr, SizeOf(TMyRecord));
pr^ := ...;

无论您用什么替换...,此代码都是不正确的。换句话说,您的代码的问题不在于使用 Default()。问题在于 GetMem 的使用。调用 GetMem 后,新分配的内存的内容是不明确的。当执行分配时,第一步是最终确定记录的当前内容。由于这些内容定义不明确,所以任何事情都可能发生。

动态分配包含托管类型的记录时,您应该使用New。如果您在这种情况下必须使用 GetMem,则需要负责确保记录中的托管成员在后续使用该记录之前得到适当的初始化。

所以在我看来,您给问题的标题是错误的。而不是

Is it safe to use Default() assignment to initialize records?

问题应该有标题

Is it safe to do anything to a record before it has been initialized?

关于delphi - 在 Delphi 中使用 Default() 赋值来初始化记录变量是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27273774/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com