2011-05-02 24 views
5

Tengo este pico para probar TPair. Puede copiar y pegar en una nueva aplicación de consola Delphi XE. He marcado la línea con la excepción:Delphi TPair Exception

Proyecto Project1.exe elevó excepción EAccessViolation clase con el mensaje 'violación de acceso en la dirección 0045042D en el módulo 'Project1.exe'. Lectura de dirección A9032D0C.

¿Alguna idea?

Gracias.

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

Dice '// <--- Error is Here', pero no dice cuál es el error en realidad. Sabiendo que eso hace que sea más fácil ayudar cuando no tienes una copia de XE instalada en la máquina, estás leyendo SO de minuto a minuto. –

+0

Lo siento ... He agregado el mensaje de error de excepción concreta. – ferpega

+0

¡Es un misterio, no puedo ver un problema en mi vida! –

Respuesta

11

Este es un error de Delphi. TDictionary<TKey,TValue>.ExtractPair no asigna Result.

RRUZ ubicado el bug in QC.

El código lee:

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 debe asignar cuando se realiza la llamada a DoRemove.

Es bastante difícil evitar este error. ExtractPair es la única forma de obtener un elemento del diccionario sin destruir la clave, por lo que debe llamarlo. Pero como no devolverá el artículo extraído, primero debe leer el artículo, recordar el valor y luego llamar al ExtractPair.

+1

@David, se permite publicar el código fuente de Delphi RTL en foros públicos? – RRUZ

+3

@RRUZ No veo ningún problema con una rutina única, especialmente cuando estamos depurando el VCL. ¿Estás de acuerdo conmigo en que este es un error directo en el código de VCL? –

+1

@David, encontré un informe de control de calidad sobre este tema, pero no sé si es un error o es por diseño. Debido al uso de 'doOwnsKeys', creo que alguien como @Barry Kelly (u otro empleado de embarcadero) puede explicar mejor esto. No puedo encontrar ninguna función similar en la clase de diccionario .Net a compare el comportamiento. – RRUZ