【问题标题】:Pascal (Script) and exception control flowPascal(脚本)和异常控制流
【发布时间】:2016-11-22 09:46:20
【问题描述】:

我正在使用 PascalScript innosetup 安装程序,但我看不到以下块的控制流向何处。

function Foo(): String;
begin
  Result := 'foo';
  RaiseException('...');
end;

procedure Test();
var
  Z : String;
begin
  Z := '';
  try
    Z := Foo();
  except
    Log(Z);
  end
end;

我的安装程序似乎表明Z 正在使用Foo 函数的Result 进行设置。我对“大多数”编程语言中的异常的理解告诉我分配 Z := Foo() 不应该在出现异常的情况下发生。

Foo 函数引发时,Z 是否仍应分配给?

【问题讨论】:

  • @MartinPrikryl:你是对的。我手工混合示例和生产代码。我让它编译并运行。

标签: exception-handling inno-setup pascal pascalscript


【解决方案1】:

可能它通过引用作为隐式第一个参数来处理结果值。但这可能会发生。它可以被认为是某些代码生成/优化的合法方法,因为它是处理返回值的一种非常常见的方式。

然而,除了测试 Delphi 所做的事情之外,Object Pascal 中确切定义的内容是模糊的领域,因为只有 x86 和 x86_64 实现。 Delphi 会返回 eax 中的值,所以如果你遵循这个逻辑,这是非法的。


稍后添加:

我用结构化类型测试了 Delphi,当它传递一个引用时,它会在堆栈上创建一个副本来传递它。

虽然这可能会使使用结构化类型优化代码变得困难,但如果需要,声明返回类型 const 的修饰符/属性可以解决此问题。

【讨论】:

  • 我用结构化类型测试了 Delphi,当它传递一个引用时,它会在堆栈上创建一个副本来传递它。所以这使它成为一个错误,即使 Delphi 通过引用传递它也可以防止这种情况(尽管以性能为代价)
  • 你的意思是“堆栈上的副本”?这里的“错误”是什么?
  • pascalscript 中的错误。在复杂/结构化返回值的情况下,FPC 和 Delphi 创建一个与返回类型相同类型的临时变量,然后通过引用传递它。调用该函数后,将结果复制到其最终目的地,这总体上避免了 PascalScript 所示的行为
  • 不,Delphi 不这样做。检查。它立即将字符串分配给 Result,而不是字符串的中间体。正如我所说,我对此进行了测试。确实,它这样做是为了记录。但不适用于字符串。
  • 它可能会为自动类型做一些不同的事情,因为无论如何都有最终确定。我没有测试过。原来的问题已经过编辑,原来是整数。
【解决方案2】:

在 Delphi 中,字符串作为结果值被视为 var 参数。换句话说,像 Foo 这样的函数实际上编译为:

procedure Foo(var Result: string);
begin
  Result := 'Foo';
  RaiseException(...);
end;

这意味着Z(通过引用参数)立即被赋值'Foo',即引发异常之前。

换句话说,函数结果不只是保存在名为Result 的局部变量中,然后在函数结束时返回——这将被异常阻止——它是立即赋值的。

我认为这正是 PascalScript 中发生的事情。

【讨论】:

  • 所以函数“知道”它的返回值会发生什么?那么函数调用如何区分A := Foo()A := '...' + Foo()呢?
  • @xtofl:因为对于'...' + Foo(),它会写入一个无法访问的中间字符串。我确定中间字符串设置为'Foo',但异常阻碍了完整表达式的形成。 IOW,确实如此:intermediate := Foo();,然后是A := '...' + intermediate;intermediate在异常之前设置为'Foo',但是完整的表达式不能继续形成,因为那是在异常之后。并且intermediate 是不可访问的,即它没有在代码中显式引用。
  • 所以在A := Foo() 的情况下没有中间字符串 - 这是优化还是在语言中定义?
  • 编译器没有理由分配和初始化中间体,因为单个调用不是复合表达式。
  • 我不明白:最简单的方法是始终拥有一个临时隐式 Result 变量,并在案例 1 中分配它,或者在案例 2 中连接它。我理解返回值优化是很有价值的,我只是想知道我是否可以依赖它:它是 Pascal 的“标准”要求吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-05
  • 2011-12-29
  • 2018-11-11
  • 1970-01-01
  • 2017-06-25
相关资源
最近更新 更多