2011-05-02 96 views
5

我有這個秒殺測試TPair。您可以複製+粘貼到新的Delphi XE控制檯應用程序上。我已經標有異常的行:德爾福TPair異常

項目PROJECT1.EXE「模塊訪問衝突在地址0045042D ‘PROJECT1.EXE’引發的異常 類EAccessViolation有消息 。閱讀 地址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. 
+0

你說'// <---錯誤在這裏,但你不會說錯誤是什麼。知道這一點,當你沒有在機器上安裝XE的副本時,可以更容易地提供幫助。 – 2011-05-02 20:56:28

+0

對不起......我添加了具體的異常錯誤消息。 – ferpega 2011-05-02 21:38:07

+0

這是一個謎,我不能爲我的生活看到一個問題! – 2011-05-02 21:56:56

回答

11

這是一個Delphi錯誤。 TDictionary<TKey,TValue>.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是在不破壞密鑰的情況下從字典中獲取項目的唯一方法,因此您必須調用它。但由於它不會返回提取的項目,因此您需要先閱讀該項目,記住該值,然後致電ExtractPair

+1

@David,是否允許在公共論壇中發佈Delphi RTL源代碼? – RRUZ 2011-05-02 22:22:22

+3

@RRUZ我沒有看到問題一個一次性的例程,特別是當我們調試VCL時,你是否同意我這是VCL代碼中的一個直接的錯誤? – 2011-05-02 22:25:02

+1

@David,我發現了關於這個問題的QC報告,但我不知道如果這是一個錯誤或者是由於設計,因爲使用'doOwnsKeys',我認爲哪個人是@Barry Kelly(或另一個embarcadero員工)可以更好地解釋這一點。我在.Net字典類中找不到類似的函數比較行爲。 – RRUZ 2011-05-02 23:24:56