【问题标题】:result in simple code when variables are uninitialized当变量未初始化时产生简单的代码
【发布时间】:2011-07-23 14:25:30
【问题描述】:

今天我的一位朋友问我以下代码:

var
  a: Integer;
begin
  ShowMessage(IntToStr(a));
end;

这是局部变量,没有被初始化好吗?

将代码放在按钮组件的 OnClick 事件中,然后以下面三种不同的方式运行代码:

  1. 点击按钮查看结果,结果=1635841
  2. 按 Enter 键并查看结果,结果 = 1
  3. 按空格键查看结果,reuslt = 1636097

我在两台不同的计算机上测试代码并看到相同的结果,对此有什么想法吗?

【问题讨论】:

  • 在我的机器上,我得到了不同的结果。每次运行程序时,我也会得到不同的结果。 (但是,根据单击按钮的方式,我认为没有区别。)
  • 我在电脑上得到的是 5734816,它是存储在 EBX 寄存器中的值))
  • 赞成,因为显然这是一个刚刚学习 Delphi 的新人。不知道为什么会投反对票?欢迎来到 SO,极客。

标签: delphi


【解决方案1】:

由于变量没有初始化,它的值可以是任何值。由于您的结果是“某物”,因此这里没有任何异常情况。

【讨论】:

  • +1 一件有趣的事情是它有时甚至会转到字符串stackoverflow.com/questions/3250827/…
  • 不@Boris,字符串结果问题是另一个问题。字符串结果实际上是由调用函数初始化的,而不是被调用函数,这就是为什么它们似乎保留在那里的值。
  • @Cosmin String 结果被实例化,而不是由调用函数初始化。如果你多次调用一个函数,结果字符串没有在函数内部赋值,如果你在两次调用之间改变内容,内容将保持不变:字符串实例被实例化,首先填充'',但不会被为每个函数调用重置为 ''。只有out aText: string; 参数会在每次调用前清除字符串。
  • @A.Bouchez,结果调用函数初始化,看调用函数的汇编序言。我并不是说每次调用之前都会初始化结果,因为它不是,它只在进入调用函数时初始化一次。但是,如果没有进行初始化,您可能会在分配函数的字符串结果时经常发生访问冲突!
  • @Cosmin 你说得完全正确——我只是担心你的评论会被误解。我区分了“instancied”(即堆栈分配期间自动生成的 asm 前缀 PString(aString)^ := nil)和“initialized”(即aString := '')。您应该在局部变量的堆栈初始化期间编写“字符串结果实际上由调用函数初始化”,而不是每次调用子函数时,否则您将不得不使用out 关键字。或类似的东西。
【解决方案2】:
procedure TForm1.Button1Click(Sender: TObject);
var
  a: Integer;
begin
    ShowMessage(IntToStr(Integer(a)));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 ShowMessage(IntToStr(Integer(Pointer(TButtonControl(Button1)))));
end;

在我的机器上,此代码生成与编译器使用 a 变量的 ebx 寄存器相同的消息,而 TButtonControl.WndProc 使用 ebx 存储指向 Self 的指针(因为在从 TbuttonControl.WndProc 调用 WinAPI 函数后,EAX 将被覆盖)这是 button1 在调用实际处理程序 Button1Click 。唉,Delphi 2007 上的消息文本太可预测了。

[已编辑] 如果您在项目编译器选项 Compiler->Debugging->Use debug DCUs 中打开 Use debug DCUs 选项,您可以在调试时查看 VCL 内部发生的情况。

【讨论】:

  • 不要将 Delphi 源代码目录添加到编译器搜索路径中。您冒着 Delphi 重新编译这些单元的风险。要通过 VCL 单元进行调试,请打开“debug DCUs”选项,将 debug-DCU 文件夹添加到搜索路径;该文件夹不包含源代码。
  • 已修复 - 似乎我时不时踩到同一个耙子
【解决方案3】:

看到这个类似的Stackoverflow question

在 Delphi 中,局部变量默认不初始化。程序员对此负责,并应始终在读取之前设置一个值。未初始化变量的值取决于用于该变量的实际分配的内存单元的内容。所以这里任何值都是可能的。

【讨论】:

  • 我知道这个!我在第一篇文章中说@“这是局部变量,没有被初始化”!
  • 那么这里的问题是什么?在 Delphi 语言级别上,您只需要知道未初始化变量的值是未定义的。如果您真的想知道到底发生了什么,您必须查看机器代码级别。但是生成的代码很大程度上取决于编译器版本和编译器标志(调试模式、优化级别等)。通常局部变量的内存是从堆栈中分配的。并且堆栈在程序执行期间会永久增长和缩小,因此新的局部变量可以包含任何值,可能是以前使用过的返回地址,但谁在乎呢?
猜你喜欢
  • 1970-01-01
  • 2016-12-12
  • 1970-01-01
  • 2011-01-07
  • 2011-05-24
  • 2016-07-31
  • 1970-01-01
  • 2013-07-04
  • 2019-05-30
相关资源
最近更新 更多