delphi – 组合匿名和嵌套过程时错误的代码

前端之家收集整理的这篇文章主要介绍了delphi – 组合匿名和嵌套过程时错误的代码前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
对于我认为是正确的Delphi代码,我有一些意外的访问冲突,但似乎被编译错误。我可以减少它
  1. procedure Run(Proc: TProc);
  2. begin
  3. Proc;
  4. end;
  5.  
  6. procedure Test;
  7. begin
  8. Run(
  9. procedure
  10. var
  11. S: PChar;
  12.  
  13. procedure Nested;
  14. begin
  15. Run(
  16. procedure
  17. begin
  18. end);
  19. S := 'Hello,world!';
  20. end;
  21.  
  22. begin
  23. Run(
  24. procedure
  25. begin
  26. S := 'Hello';
  27. end);
  28. Nested;
  29. ShowMessage(S);
  30. end);
  31. end;

对我来说会发生什么呢S:=’你好,世界!存储在错误的位置。因此,引发访问冲突,或ShowMessage(S)显示“Hello”(有时候,释放用于实现匿名过程的对象时会引发访问冲突)。

我使用的是Delphi XE,所有更新都安装了。

我怎么知道这会造成什么问题?我知道如何重写我的代码以避免匿名过程,但我无法确定哪些情况导致错误代码,所以我不知道在哪里避免它们。

如果这是在Delphi的后期版本中修复的,那么有趣的是,在这一点上升级不是一个选择。

在QC上,最近的报告我可以找到类似的#91876,但是在Delphi XE中解决了。

更新:

根据AlexSC的评论,稍作修改

  1. ...
  2.  
  3. procedure Nested;
  4. begin
  5. Run(
  6. procedure
  7. begin
  8. S := S;
  9. end);
  10. S := 'Hello,world!';
  11. end;
  12.  
  13. ...

工作。

生成的机器代码

  1. S := 'Hello,world!';

在失败的程序是

  1. ScratchForm.pas.44: S := 'Hello,world!';
  2. 004BD971 B89CD94B00 mov eax,$004bd99c
  3. 004BD976 894524 mov [ebp+$24],eax

而正确的版本是

  1. ScratchForm.pas.45: S := 'Hello,world!';
  2. 004BD981 B8B0D94B00 mov eax,$004bd9b0
  3. 004BD986 8B5508 mov edx,[ebp+$08]
  4. 004BD989 8B52FC mov edx,[edx-$04]
  5. 004BD98C 89420C mov [edx+$0c],eax

失败的程序中生成代码没有看到S被移动到编译器生成的类,[ebp $ 24]是如何访问嵌套方法的外部局部变量如何访问局部变量。

解决方法

没有看到整个汇编代码整个(过程测试),只是假设在您发布的代码段,可能是在失败的代码段只有一个指针已被移动到正确的版本上有一些数据移动。

所以似乎S:= S或S:=”导致编译器自己创建引用,甚至可以分配一些内存,这将解释为什么它的工作原理。

我也假设这是为什么一个访问冲突发生没有S:= S或S:=”,因为如果没有为String分配的内存(记住你只声明了S:PChar),则会引发访问冲突,因为未分配已访问内存

如果您只是简单地声明S:String,这可能不会发生。

扩展后添加评论

PChar只是数据结构指针,必须存在。 PChar的另一个常见问题是声明本地变量,然后将PChar传递给该变量到其他Procs,因为发生了什么是本地变量在程序结束后被释放,但PChar仍然会指向它,然后提高访问一次访问冲突。

每个文档存在的唯一可能性就是声明像这样的const S:PChar =’Hello,world!这是因为编译器可以解析一个相对的Adresse。但这仅适用于常量,而不适用于上述示例中的变量。像上面的例子一样,需要将存储分配给PChar所指向的字符串文字,如S:String; P:PChar S:=’你好,世界! P:= PChar(S);或类似物。

如果它仍然失败,声明String或整数,那么也许该变量消失在某处,或突然在proc中不可见,但这将是与现有PChar问题无关的另一个问题。

定论:

可以做S:PChar S:=’你好,世界!但是编译器然后简单地将其分配为局部或全局常量,如const S:PChar =’Hello,world!确实被保存到可执行文件中,第二个S:=’Hello’然后创建另一个也保存到可执行文件中,等等 – 但是S只指向最后一个分配,所有其他仍然在可执行但不可访问不知道确切的位置,因为S只指向最后一个分配。

所以取决于哪一个是最后一个S指向你好,世界!或者你好在上面的例子中,我只能猜测哪一个是最后一个,谁知道编译器也只能猜测,并且取决于优化和其他不可预测的因素S可以突然指向未分配的Mem而不是最后一个由Time Showmessage(S)被执行,然后引发访问冲突。

猜你在找的Delphi相关文章