2016-12-08 5 views
8

मैं डेल्फी 10 में एक बग पर ठोकर खाई सिएटल अद्यतन 1. निम्नलिखित कोड लेते हैं:TList <_AnyDynamicArrays_> के साथ डेल्फी 10 की बग के आसपास कैसे काम करें?

procedure TForm1.Button1Click(Sender: TObject); 
begin 
//----------We crash here---------------- 
    FList.Items[0] := SplitString('H:E', ':'); 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    FList := TList<TStringDynArray>.Create; 
    FList.Add(SplitString('H:E', ':')); 
    FList.Items[0] := SplitString('H:E', ':'); 
end; 

पहली नज़र में, यह लगता है कि TList<T> ठीक से गतिशील सरणियों इसमें के जीवनकाल का प्रबंधन नहीं है, लेकिन फिर, यह 64 बिट्स में संकलित होने पर ठीक काम करता है, यह केवल 32 बिट्स में क्रैश होता है (मुझे लगता है कि इसका मतलब यह नहीं है कि बग 64 बिट्स में मौजूद नहीं है ...)।

ध्यान दें कि स्प्लिटस्ट्रिंग का उपयोग किया गया था क्योंकि अगर पहला कार्य एक गतिशील सरणी लौटा रहा था जो मेरे दिमाग में आया था। मूल समस्या TList<TBookmark> के साथ सामने आई थी जो एक ही समस्या को प्रदर्शित करता है।

यह बग इस तरह प्रक्रिया Button1Click पुनर्लेखन को हल करने के लिए संभव है:

procedure TForm1.Button1Click(Sender: TObject); 
var MyArray : TStringDynArray; 
begin 
    MyArray := FList.Items[0]; 
    FList.Items[0] := SplitString('H:E', ':'); 
    //----------Yeah! We don't crash anymore!----------- 
end; 

लेकिन चारों ओर मेरे सभी अनुप्रयोग उन्हें संशोधित इस बग के आसपास काम करने के लिए वास्तव में मेरे पसंदीदा विकल्प नहीं होगा जा रहा है। मैं अपमानजनक दिनचर्या को अधिक पसंद करता हूं और यदि संभव हो तो इसे स्मृति में पैच करना चाहता हूं।

अगर किसी को भी इस समस्या का सामना करना पड़ा और कोई कामकाज मिला, तो मैं आभारी रहूंगा। अन्यथा, जब मैं उचित कार्यवाही पाता हूं तो मैं अपना पोस्ट करूंगा।

इसके अलावा, कृपया टिप्पणी करें कि समस्या अभी भी बर्लिन में मौजूद है या नहीं।

+0

एक ही त्रुटि। –

+1

सामान्य 'TList' के साथ रिपोर्ट की गई बग से, यह एक minefield लगता है। –

उत्तर

8

आखिरकार, बग अभी भी 64 बिट्स में था। यह TStringDynArray के लिए क्रैश नहीं हुआ, लेकिन यह अन्य गतिशील सरणी प्रकारों के लिए किया था।

समस्या के स्रोत Generics.Collections में निम्न कोड में पाया जाता है:

procedure TListHelper.DoSetItemDynArray(const Value; AIndex: Integer); 
type 
    PBytes = ^TBytes; 
var 
    OldItem: Pointer; 
begin 
    OldItem := nil; 
    try 
    CheckItemRangeInline(AIndex); 

    TBytes(OldItem) := PBytes(FItems^)[AIndex]; 
    PBytes(FItems^)[AIndex] := TBytes(Value); 

    FNotify(OldItem, cnRemoved); 
    FNotify(Value, cnAdded); 
    finally 
    DynArrayClear(OldItem, FTypeInfo); //Bug is here. 
    end; 
end; 

क्या है, गलत TypeInfo DynArrayClear को पारित कर दिया है। TList<TStringDynArray> के मामले में, TypeInfo(TArray<TStringDynArray>)TypeInfo(TStringDynArray) के बजाय पारित किया गया है। जो मैं बता सकता हूं, उचित कॉल है:

DynArrayClear(OldItem, pDynArrayTypeInfo(NativeInt(FTypeInfo) + pDynArrayTypeInfo(FTypeInfo).Name).elType^); 

निजी होने की प्रक्रिया इसे रोकना जटिल बनाती है। मैंने इस तथ्य का उपयोग करके ऐसा किया कि रिकार्ड हेल्पर अभी भी डेल्फी 10 में रिकॉर्ड्स के निजी सेक्शन तक पहुंच सकता है। मुझे लगता है कि यह बर्लिन के उपयोगकर्ताओं के लिए अधिक जटिल होगा।

function TMyHelper.GetDoSetItemDynArrayAddr: TDoSetItemDynArrayProc; 
begin 
    Result := Self.DoSetItemDynArray; 
end; 

उम्मीद है, Embarcadero यह किसी दिन बर्लिन Upd2 में ठीक कर देंगे ...

+0

'pDynArrayTypeInfo (मूल INT (FTypeInfo) + pDynArrayTypeInfo (FTypeInfo)। नाम) .elType^'अगर आप' ElType' का उपयोग करते हैं तो आपको वह मिलता है। –

+5

रिपोर्ट किया गया: [आरएसपी -16511: TListHelper.DoSetItemDynArray() में क्रैश गलत टाइपइन्फो के कारण पुरानी गतिशील सरणी को साफ़ करने के लिए उपयोग किया जाता है] (https://quality.embarcadero.com/browse/RSP-16511) –

+1

यह लगभग है जैसे वे इस सहायक में प्रत्येक विशेष मामले के लिए यूनिट परीक्षण नहीं लिखा ........ –

संबंधित मुद्दे

 संबंधित मुद्दे