【问题标题】:Delphi TPair ExceptionDelphi TPair 异常
【发布时间】:2011-08-17 05:44:39
【问题描述】:

我有这个尖峰来测试 TPair。您可以在新的 Delphi XE 控制台应用程序上复制+粘贴。我已经标记了例外的行:

Project Project1.exe 引发异常 带有消息的 EAccessViolation 类 '地址0045042D的访问冲突 在模块“Project1.exe”中。阅读 地址 A9032D0C。

有什么想法吗?

谢谢。

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Generics.Defaults,
  Generics.Collections;

type
  TProduct = class
  private
    FName: string;
    procedure SetName(const Value: string);
  published
  public
    property Name: string read FName write SetName;
  end;

type
  TListOfProducts = TObjectDictionary<TProduct, Integer>;

{ TProduct }

procedure TProduct.SetName(const Value: string);
begin
  FName := Value;
end;


var
  MyDict: TListOfProducts;
  MyProduct1: TProduct;
  MyProduct2: TProduct;
  MyProduct3: TProduct;
  APair: TPair<TProduct, Integer>;
  aKey: string;

begin
  try
    MyDict := TListOfProducts.Create([doOwnsKeys]);
    MyProduct1 := TProduct.Create;
    MyProduct1.Name := 'P1';
    MyProduct2 := TProduct.Create;
    MyProduct2.Name := 'P2';
    MyProduct3 := TProduct.Create;
    MyProduct3.Name := 'P3';

    MyDict.Add(MyProduct1, 1);
    MyDict.Add(MyProduct2, 2);
    MyDict.Add(MyProduct3, 3);

    APair := MyDict.ExtractPair(MyProduct1);
    Writeln(APair.Key.Name);   // <--- Error is Here.
    Writeln(IntToStr(APair.Value));

    Readln(aKey);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

【问题讨论】:

  • 你说// &lt;--- Error is Here.,但你没有说错误实际上是什么。当您现在正在阅读 SO 的机器上没有安装 XE 的副本时,知道这一点可以更轻松地提供帮助。
  • 对不起...我已经添加了具体的异常错误消息。
  • 这是个谜,我一辈子都看不到问题!
  • 你的意思是所有的源代码都是正确的吗?那会更糟...... :-(你能在你的Delphi IDE安装中重现这个问题吗?
  • 如果我在ExtractPair 语句之前添加这一行:APair := TPair&lt;TProduct, Integer&gt;.Create(MyProduct3, 0);,那么我没有异常,但我在APair var 中也没有MyProduct1 数据。

标签: delphi generics exception delphi-xe


【解决方案1】:

这是一个 Delphi 错误。 TDictionary&lt;TKey,TValue&gt;.ExtractPair 不分配 Result

RRUZ 找到了bug in QC

代码如下:

function TDictionary<TKey,TValue>.ExtractPair(const Key: TKey): TPair<TKey,TValue>;
var
  hc, index: Integer;
begin
  hc := Hash(Key);
  index := GetBucketIndex(Key, hc);
  if index < 0 then
    Exit(TPair<TKey,TValue>.Create(Key, Default(TValue)));

  DoRemove(Key, hc, cnExtracted);
end;

Result 应在调用DoRemove 时分配。

解决这个错误非常困难。 ExtractPair 是在不破坏密钥的情况下从字典中取出项目的唯一方法,因此您必须调用它。但是由于它不会返回提取出来的item,所以需要先读取item,记住值,然后调用ExtractPair

【讨论】:

  • @David,是否允许在公共论坛上发布 Delphi RTL 源代码?
  • @RRUZ 我认为一次性例程没有问题。尤其是在我们调试 VCL 时。你同意我的观点,这是 VCL 代码中的一个简单错误吗?
  • @Rruz,美国法律允许出于审查和批评等目的复制受版权保护作品的有限部分。它被称为合理使用。我确信大卫的回答符合标准。
  • @RRUZ 那个 QC 报告确实是同一个错误。 QC 系统没有修复如此明显的错误,这非常令人失望。请记住,这是 16 个月前报告的!
  • @A.Bouchez 确实如此。让我感到震惊的另一件事是,该错误被报告给 QC,然后他们制作了另一个保留该错误的主要版本。这种情况发生得太频繁了。
猜你喜欢
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
  • 2013-09-13
  • 2011-01-06
相关资源
最近更新 更多