delphi中的变量初始值

时间:2009-02-12 11:50:09

标签: delphi

我相信delphi中的局部整数变量没有初始化为零。初始值是在该存储器位置发生的任何事情。 因此,在第一次单击按钮时,下面的代码中,第一条消息显示整数值。 为什么第二次点击它不会显示3而是显示相同的整数 值?每次单击按钮时,它都会继续显示相同的整数值。仅当我停止并重新启动程序时,该值才不同。 3存储在哪里,因为看起来每次在程序的同一次运行中单击按钮时使用相同的内存位置?

procedure TForm1.Button1Click(Sender: TObject);

var
int1 : integer;

begin
   showmessage(inttostr(int1)) ;
   int1 := 3;
end;

end.

6 个答案:

答案 0 :(得分:12)

kjack,

它包含当时堆栈帧中的任何值。在你的情况下,这将是发件人。如果您将整数和类型转换为对象,您会注意到“模式”。

procedure TForm1.Button1Click(Sender: TObject);

var
int1 : integer;

begin
   ShowMessage(TObject(int1).ClassName);
   showmessage(inttostr(int1)) ;
   int1 := 3;
end;

end.

答案 1 :(得分:5)

首先,你是正确的局部变量aren't initialised

此外,您无法保证int1在每次调用时都存储在同一内存位置。在这种情况下,你可能每次看到相同值的原因是因为它 使用相同的位置(偶然)但是Delphi编译器已经优化了你的最终

int1 := 3;

声明,因为它没有效果。 (您可以在该行之后添加另一个showmessage(inttostr(int1))调用,看看是否会产生影响。)另一种可能性是,用于int1的内存位置在对按钮处理程序的调用之间重复使用(例如在Windows中)消息循环)并且总是将其重置为您正在看到的值。

答案 2 :(得分:2)

只有在Button1上两次单击之间不执行其他代码时才会出现这种情况,最重要的是使用相同数量(或更多)堆栈空间的代码,而不是代码到达TForm1.Button1Click()使用的过程。除非您覆盖堆栈上的值,否则它们仍将包含相同的值。

您可以做的是测试这个是添加另一个带有OnClick处理程序的按钮,该处理程序调用的参数比ShowMessage()具有的参数多。如果在Button1上单击两次之间单击该按钮,则int1的值确实应该更改。这是因为Button1Click()中int1的堆栈位置将用于其他处理程序中的一个参数,并被覆盖。

应该优化分配,你可以看到这一点,因为线不应该在排水沟区域有蓝点。还应该有编译器提示。

编辑:当您评论时,单击其他按钮时的行为似乎没有变化。从那里我只能假设VCL代码(在调用OnClick处理程序之前执行)使用了这么多的堆栈空间,int1的内存位置总是用一些(稳定)值初始化。此代码始终相同,因此如果涉及的对象(应用程序,父窗体和按钮)的地址不更改,则值也将保持不变。 OTOH重新启动应用程序将在未初始化的局部变量中产生一个新的,同样稳定的值。

请注意,这一切都高度依赖于在处理程序之前执行的VCL代码,因此对VCL的更改也可能会更改它。甚至可能是各种Delphi版本的表现不同。

答案 3 :(得分:1)

局部变量位于堆栈框架中。它们没有初始化。

如果您访问方法两次,则堆栈指针有可能是euqal,它提供相同的值。

示例:

通话前堆叠:

> More stack  (memory location X)

如果调用Button1Click,则堆栈如下:

> Int1
> Return address
> Sender
> Self pointer
> More stack  (memory location X)

如果下次调用Button1Click,堆栈指针仍在位置X上,并且没有其他函数更改了值,您将找到Int1的相同值。

如果你有安全的信息,清除局部变量总是明智的(但你有可能优化器会删除这些状态。所以你需要禁用优化)。

只是为了好玩,添加另一个按钮:

procedure TForm1.Button2Click(Sender: TObject);
var
  int1 : integer;
begin
  showmessage(inttostr(int1)) ;
  int1 := 777;
end;

并检查:

  • 点击1:垃圾
  • 再次点击1:3
  • 点击2:3
  • 点击1:777

答案 4 :(得分:1)

你想要它是一样的吗?如果是这样,您可以使用本地const:

procedure TForm1.Button1Click(Sender: TObject);
const
  i: integer = 0;
begin
  i := i + 1;
  edit1.text := intToStr(i);
end;

你必须确保'可分配的类型常量'已打开。

答案 5 :(得分:0)

初始化变量可能由内存管理器完成,也可能不由内存管理器完成。

我认为任何内存管理器都可以将所有变量初始化为零(0x0000)。那也是在.Net中完成的。