为什么大多数Delphi示例使用FillChar()来初始化记录? [英] Why most Delphi examples use FillChar() to initialize records?

查看:192
本文介绍了为什么大多数Delphi示例使用FillChar()来初始化记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是想知道,为什么大多数Delphi示例使用FillChar()来初始化记录。

  type 
TFoo = record
i:整数;
s:string; //不安全的记录,更好地使用PChar而不是
结束;

const
EmptyFoo:TFoo =(i:0; s:'');

程序测试;
var
Foo:TFoo;
s2:string;
begin
Foo:= EmptyFoo; //初始化记录

//危险代码开始
FillChar(Foo,SizeOf(Foo),#0);
s2:= Copy(泄漏测试,1,MaxInt); // string buffer的引用计数= 1
Foo.s = s2; // s2 = 2
FillChar(Foo,SizeOf(Foo),#0)的引用计数; //指数预计为1,但仍然是2
结束;
//退出该过程后,字符串缓冲区仍然有1个引用。该字符串缓冲区被视为内存泄漏。

这里( http://stanleyxu2005.blogspot.com/2008/01/potential-memory-leak-by-initializing.html )是我的注意这个话题。 IMO,声明一个常数,默认值是一个更好的方法。

解决方案

历史原因,主要是。 FillChar()可追溯到Turbo Pascal天,并被用于此类目的。这个名字真的有点不正确,因为当说Fill Char ()时,它真的是Fill Byte ()。原因是最后一个参数可以使用char 一个字节。所以FillChar(Foo,SizeOf(Foo),#0)和FillChar(Foo,SizeOf(Foo),0)是等价的。另一个混乱的原因是,截至Delphi 2009,FillChar仍然只填充字节,即使Char相当于WideChar。在查看FillChar最常见的用法时,为了确定大多数人是否使用FillChar来实际使用字符数据填充内存,或者只是使用它来以某个给定的字节值初始化内存,我们发现后一种情况主导其使用而不是前者。因此,我们决定保持FillChar以字节为中心。



确实,使用FillChar清除包含使用托管类型之一(字符串)声明的字段的记录,变体,接口,动态数组)如果不在正确的上下文中使用,则可能不安全。然而,在您给出的示例中,只要在该范围内记录的第一件事件,就可以在本地声明的记录变量上调用FillChar。原因是编译器已经生成代码来初始化记录中的字符串字段。这将已经将字符串字段设置为0(nil)。调用FillChar(Foo,SizeOf(Foo),0)将只覆盖0个字节的整个记录​​,包括已经为0的字符串字段。在之后的记录变量上使用FillChar将值分配给字符串字段,不推荐。使用初始化的常量技术是一个非常好的解决方案,因为编译器可以生成正确的代码,以确保在分配过程中正确完成现有的记录值。


I just wondered, why most Delphi examples use FillChar() to initialize records.

type
  TFoo = record
    i: Integer;
    s: string; // not safe in record, better use PChar instead
  end;

const
  EmptyFoo: TFoo = (i: 0; s: '');

procedure Test;
var
  Foo: TFoo;
  s2: string;
begin
  Foo := EmptyFoo; // initialize a record

  // Danger code starts
  FillChar(Foo, SizeOf(Foo), #0);
  s2 := Copy("Leak Test", 1, MaxInt); // The refcount of the string buffer = 1
  Foo.s = s2; // The refcount of s2 = 2
  FillChar(Foo, SizeOf(Foo), #0); // The refcount is expected to be 1, but it is still 2
end;
// After exiting the procedure, the string buffer still has 1 reference. This string buffer is regarded as a memory leak.

Here (http://stanleyxu2005.blogspot.com/2008/01/potential-memory-leak-by-initializing.html) is my note on this topic. IMO, declare a constant with default value is a better way.

解决方案

Historical reasons, mostly. FillChar() dates back to the Turbo Pascal days and was used for such purposes. The name is really a bit of a misnomer because while it says FillChar(), it is really FillByte(). The reason is that the last parameter can take a char or a byte. So FillChar(Foo, SizeOf(Foo), #0) and FillChar(Foo, SizeOf(Foo), 0) are equivalent. Another source of confusion is that as of Delphi 2009, FillChar still only fills bytes even though Char is equivalent to WideChar. While looking at the most common uses for FillChar in order to determine whether most folks use FillChar to actually fill memory with character data or just use it to initialize memory with some given byte value, we found that it was the latter case that dominated its use rather than the former. With that we decided to keep FillChar byte-centric.

It is true that clearing a record with FillChar that contains a field declared using one of the "managed" types (strings, Variant, Interface, dynamic arrays) can be unsafe if not used in the proper context. In the example you gave, however, it is actually safe to call FillChar on the locally declared record variable as long as it is the first thing you ever do to the record within that scope. The reason is that the compiler has generated code to initialize the string field in the record. This will have already set the string field to 0 (nil). Calling FillChar(Foo, SizeOf(Foo), 0) will just overwrite the whole record with 0 bytes, including the string field which is already 0. Using FillChar on the record variable after a value was assigned to the string field, is not recommended. Using your initialized constant technique is a very good solution this problem because the compiler can generate the proper code to ensure the existing record values are properly finalized during the assignment.

这篇关于为什么大多数Delphi示例使用FillChar()来初始化记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆