【问题标题】:Compiler warning "return value might be undefined"编译器警告“返回值可能未定义”
【发布时间】:2011-09-28 01:15:50
【问题描述】:

我经常使用以下代码:

function GetNumber(Handle : THandle) : Integer;
begin
FLock.BeginRead;
try
  if FMap.TryGetValue(Handle, Object) then
    raise EArgumentException.Create('Invalid handle');
  Result := Object.Number;
finally
  FLock.EndRead;
end;
end;

不幸的是,编译器对所有这些方法都给出了警告:

[DCC Warning] Unit.pas(1012): W1035 Return value of function 'GetNumber' might be undefined

我知道这个警告,但在这种情况下,我根本看不出有任何原因。或者是否有我遗漏的情况会导致未定义的结果值?我理解try..except 的警告,但对于try..finally,这对我来说没有意义。

问题:

  • 警告有什么原因吗?
  • 我怎样才能摆脱它(将Result := Object.Number 行移出锁定不是一种选择,我想避免在每个函数的顶部写一个完全不必要的Result := 0 行)

谢谢!

【问题讨论】:

  • +1。不幸的是,我不得不处理几次。你会在我的代码中找到一些Result := X; // Avoid compiler warning,其中一些是有条件编译的,因为版本之间的编译器发生了变化。 Embarcadero 应该修复这个错误,因为它很烦人!

标签: delphi compiler-warnings delphi-xe


【解决方案1】:

这是一个编译器错误。如果try/finally 被删除,则不会发出警告。编译器早就能够认识到raise 免除了编码器分配返回值的义务。无论出于何种原因,try/finally 似乎都混淆了它的分析。


再想一想,也许这不是编译器错误。如果finally 块中的代码停止了异常传播怎么办?显然没有except 处理程序,但我更怀疑SystemSysUtils 单元中的异常支持例程之一可能能够阻止异常进一步发展。

【讨论】:

  • "但我更怀疑 System 或 SysUtils 单元中的异常支持例程之一可能能够阻止异常进一步发展" 是什么让你这么认为?他们为什么要这样做?
  • @Smasher 我现在不太确定。我在想AcquireExceptionObject 会阻止异常的进展,但我认为不会。
  • 如果没有raise 语句而只是try …; Result := …; finally … end;,则不会有返回值未定义警告,即使在到达结果赋值语句之前仍然可能出现异常。
  • 移除try/finally 移除锁的资源保护!第一个例外,你永远不会解锁。此外,如果 finally 能够阻止/停止异常弹出 - 手头有一个更严重的问题!
  • @Craig 我担心您完全误解了我的帖子的主旨并浪费了您宝贵的反对票。当然,我并不主张 OP 删除 try/finally。那将是疯狂的。我要说的是 try/finally 和编译器警告之间的交互。没有 try/finally 时不会发出警告,即使它对是否设置返回值没有影响。
【解决方案2】:

警告有什么原因吗?

我看不到一个,但它在那里是因为raise

我怎样才能摆脱它(将 Result := Object.Name 行移出 锁不是一种选择,我想要 避免完全写一个 不必要的结果 := 0 行在顶部 每个函数)

将 raise 语句移动到它自己的过程中。

function GetNumber(Handle : THandle) : Integer;
    procedure InvHandle;
    begin
        raise EArgumentException.Create('Invalid handle');
    end;
begin
    FLock.BeginRead;
    try
        if FMap.TryGetValue(Handle, Object) then
            InvHandle;
        Result := Object.Number;
    finally
        FLock.EndRead;
    end;
end;

【讨论】:

  • 加薪真的不是问题。编译器早就认识到,带有 raise 的代码路径免除了编码器分配给返回值的义务。尝试编译 OP 的代码,但删除 Try/Finally!
  • @David – 没有 try..finally 就没有编译器警告。但我认为删除 try..finally 块并不是解决手头问题的好方法。移动 raise 语句也会删除警告,所以我猜编译器中的错误与在 try..finally 块中使用 raise 的组合有关。
  • @Mickael 我并不是说解决方案是删除try/finally!!!我要说的是,这显然是一个编译器错误。
  • @David - 你怎么能确定这是try/finally 的问题,但不是raise 的问题?删除其中任何一个即可解决警告?!
  • @lieven 没有提出它是一个根本不同的问题。不管怎样,不管是什么原因,都有问题。
【解决方案3】:

一个任务

Result := ...;

finally 块中缺失。

【讨论】:

  • except 块需要额外的结果 - 而不是 finally 块。
猜你喜欢
  • 2011-05-11
  • 2017-12-21
  • 2014-04-12
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多