在 Delphi 中初始化了哪些变量? [英] Which variables are initialized when in Delphi?

查看:19
本文介绍了在 Delphi 中初始化了哪些变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我一直听说类字段(基于堆)被初始化,但基于堆栈的变量没有.我还听说记录成员(也是基于堆栈的)也没有初始化.编译器警告未初始化局部变量([DCC 警告] W1036 变量 'x' 可能尚未初始化),但不会警告记录成员.所以我决定进行一个测试.

对于所有记录成员,我总是从 Integers 获取 0,从 Booleans 获取 false.

我尝试打开和关闭各种编译器选项(调试、优化等),但没有任何区别.我所有的记录成员都在初始化.

我错过了什么?我使用的是 Delphi 2009 Update 2.

program TestInitialization;{$APPTYPE 控制台}用途系统实用程序;类型TR = 记录上市i1、i2、i3、i4、i5:整数;a:整数数组[0..10];b1、b2、b3、b4、b5:布尔值;s:字符串;结尾;无功r:TR;x:整数;开始尝试WriteLn('测试记录...');WriteLn('i1',R.i1);WriteLn('i2',R.i2);WriteLn('i3',R.i3);WriteLn('i4',R.i4);WriteLn('i5',R.i5);Writeln('S',R.s);Writeln('Booleans: ', R.b1, ' ', R.b2, ' ', R.b3, ' ', R.b4, ' ', R.b5);Writeln('数组');对于 x := 0 到 10 做写(R.a[x], ' ');写Ln;WriteLn('完成......');除了在 E:Exception 上做Writeln(E.Classname, ':', E.Message);结尾;读Ln;结尾.

输出:

<前>测试记录....1 00i3 0i4 0i5 0秒布尔值: FALSE FALSE FALSE FALSE FALSE大批0 0 0 0 0 0 0 0 0 0 0完毕 ....

解决方案

全局变量是零初始化的.在程序的主要 begin..end 块的上下文中使用的变量可能是一种特殊情况;有时它们被视为局部变量,特别是 for 循环索引器.但是,在您的示例中,r 是一个全局变量,从可执行文件的 .bss 部分分配,Windows 加载程序确保该部分为零填充.

局部变量被初始化,就像它们被传递到 Initialize 例程一样.Initialize 例程使用运行时类型信息 (RTTI) 将字段(递归 - 如果字段是数组或记录类型)和数组(递归 - 如果元素类型是数组或托管类型的记录),其中托管类型是以下之一:

  • AnsiString
  • UnicodeString
  • 宽字符串
  • 接口类型(包括方法引用)
  • 动态数组类型
  • 变体

来自堆的分配不一定要初始化;这取决于用于分配内存的机制.作为实例对象数据一部分的分配由 TObject.InitInstance 填充为零.来自 AllocMem 的分配是零填充的,而 GetMem 分配不是零填充的.来自 New 的分配被初始化,就像它们被传递到 Initialize 一样.

So I always heard that class fields (heap based) were initialized, but stack based variables were not. I also heard that record members (also being stack based) were also not initialized. The compiler warns that local variables are not initialized ([DCC Warning] W1036 Variable 'x' might not have been initialized), but does not warn for record members. So I decided to run a test.

I always get 0 from Integers and false from Booleans for all record members.

I tried turning various compiler options (debugging, optimizations, etc.) on and off, but there was no difference. All my record members are being initialized.

What am I missing? I am on Delphi 2009 Update 2.

program TestInitialization;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TR = Record
  Public
    i1, i2, i3, i4, i5: Integer;
    a: array[0..10] of Integer;
    b1, b2, b3, b4, b5: Boolean;
    s: String;
  End;

var
  r: TR;
  x: Integer;

begin
  try
    WriteLn('Testing record. . . .');
    WriteLn('i1 ',R.i1);
    WriteLn('i2 ',R.i2);
    WriteLn('i3 ',R.i3);
    WriteLn('i4 ',R.i4);
    WriteLn('i5 ',R.i5);

    Writeln('S ',R.s);

    Writeln('Booleans: ', R.b1, ' ', R.b2, ' ', R.b3, ' ', R.b4, ' ', R.b5);

    Writeln('Array ');
    for x := 0 to 10 do
      Write(R.a[x], ' ');
    WriteLn;

    WriteLn('Done . . . .');
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
  ReadLn;
end.

Output:

Testing record. . . .
i1 0
i2 0
i3 0
i4 0
i5 0
S
Booleans: FALSE FALSE FALSE FALSE FALSE
Array
0 0 0 0 0 0 0 0 0 0 0
Done . . . .

解决方案

Global variables are zero-initialized. Variables used in the context of the main begin..end block of a program can be a special case; sometimes they are treated as local variables, particularly for-loop indexers. However, in your example, r is a global variable and allocated from the .bss section of the executable, which the Windows loader ensures is zero-filled.

Local variables are initialized as if they were passed to the Initialize routine. The Initialize routine uses runtime type-info (RTTI) to zero-out fields (recursively - if a field is of an array or record type) and arrays (recursively - if the element type is an array or a record) of a managed type, where a managed type is one of:

  • AnsiString
  • UnicodeString
  • WideString
  • an interface type (including method references)
  • dynamic array type
  • Variant

Allocations from the heap are not necessarily initialized; it depends on what mechanism was used to allocate memory. Allocations as part of instance object data are zero-filled by TObject.InitInstance. Allocations from AllocMem are zero-filled, while GetMem allocations are not zero-filled. Allocations from New are initialized as if they were passed to Initialize.

这篇关于在 Delphi 中初始化了哪些变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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