2012-10-11 6 views
5

नीचे दिए गए कोड पर विचार करें जो डेल्फी 6 में त्रुटि के बिना संकलित और चलाता है। जब मैं गतिशील स्ट्रिंग सरणी को पुनर्प्राप्त करता हूं, sa में खाली सरणी देखने के बजाय, मुझे एक तत्व के साथ 1 की लंबाई वाला सरणी दिखाई देती है जिसमें एक तत्व होता है खाली स्ट्रिंग। यह क्यों है और मैं सुरक्षित रूप से एक एनआईएल गतिशील सरणी को एक संस्करण में कैसे आवंटित कर सकता हूं और इसे ठीक से ठीक कर सकता हूं? यहां कोड है:किसी भिन्नता को एनआईएल सरणी निर्दिष्ट करने से डेल्फी 6 में एक गैर-खाली सरणी वापस क्यों आती है?

TDynamicStringArray = array of string; 

var 
    V: Variant; 
    sa: TDynamicStringArray; 
begin 
    sa := nil; 

    V := sa; 

    sa := V; 

    OutputDebugString('sa has a single element now with an empty string in it when I expect it to be empty.'); 
end; 
+0

शायद समान किरदार 'संस्करण है -> स्ट्रिंग -> बल्कि' से strings' की सरणी संस्करण -> सूचक -> strings' –

उत्तर

5

यहां दो बग हैं।

Variants.DynArrayVariantBounds में सबसे पहले। जब गतिशील सरणी nil होती है तो यह ग़लत ढंग से (0, 0) की निम्न/उच्च सीमा वाली जोड़ी देता है। इसे (0, -1) वापस करना चाहिए। यह बग डेल्फी के नवीनतम संस्करणों में तय है। इससे V := sa का कारण एक एकल, खाली, तत्व के साथ एक संस्करण सरणी लौटाता है।

दूसरा बग, दूसरी दिशा को प्रभावित करता है sa := V। यह बग अभी भी डेल्फी के नवीनतम संस्करणों में मौजूद है। यह बग Variants.DynArrayFromVariant में है। एक repeat/until लूप है जो इनपुट संस्करण सरणी पर चलता है और आउटपुट गतिशील सरणी को पॉप्युलेट करता है। जब इनपुट संस्करण सरणी खाली होती है, तो उसे repeat/until लूप दर्ज नहीं करना चाहिए। हालांकि, कोड गलती से ऐसा करता है और VarArrayGet के साथ संस्करण सरणी के तत्व को पढ़ने का प्रयास करता है। चूंकि सरणी खाली है, जो रनटाइम त्रुटि को उत्तेजित करती है। मैंने यह रिपोर्ट की है: QC#109445

यहाँ एक बहुत ही बस कोड है कि बग ठीक करता है की बिट है। ध्यान दें कि मैंने केवल उस मामले पर विचार किया है जहां सरणी एक आयामी हैं। यदि आपको उच्च आयामी सरणी का समर्थन करने की आवश्यकता है तो आप ऐसा करने के लिए इस दृष्टिकोण को बढ़ा सकते हैं।

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    Variants; 

var 
    OriginalVarFromDynArray: procedure(var V: Variant; const DynArray: Pointer; TypeInfo: Pointer); 
    OriginalVarToDynArray: procedure(var DynArray: Pointer; const V: Variant; TypeInfo: Pointer); 

function DynArrayVarType(typeInfo: PDynArrayTypeInfo): Integer; 
const 
    tkDynArray = 17; 
begin 
    Result := varNull; 
    if (typeInfo<>nil) and (typeInfo.Kind=tkDynArray) then 
    begin 
    Inc(PChar(typeInfo), Length(typeInfo.name)); 
    Result := typeInfo.varType; 
    if Result=$48 then 
     Result := varString; 
    end; 
    if (Result<=varNull) or (Result=$000E) or (Result=$000F) or ((Result>varInt64) and not (Result=varString)) then 
    VarCastError; 
end; 

procedure VarFromDynArray(var V: Variant; const DynArray: Pointer; TypeInfo: Pointer); 
var 
    VarType, DynDim: Integer; 
begin 
    DynDim := DynarrayDim(PDynArrayTypeInfo(TypeInfo)); 
    if DynDim=1 then 
    begin 
    //only attempt to deal with 1 dimensional arrays 
    if DynArray=nil then begin 
     VarClear(V); 
     VarType := DynArrayVarType(PDynArrayTypeInfo(TypeInfo)); 
     if VarType = varString then 
     VarType := varOleStr; 
     V := VarArrayCreate([0, -1], VarType); 
     exit; 
    end; 
    end; 
    OriginalVarFromDynArray(V, DynArray, TypeInfo); 
end; 

procedure VarToDynArray(var DynArray: Pointer; const V: Variant; TypeInfo: Pointer); 
var 
    DimCount: Integer; 
    Len: Integer; 
begin 
    DimCount:= VarArrayDimCount(V); 
    if DimCount=1 then 
    begin 
    //only attempt to deal with 1 dimensional arrays 
    Len := VarArrayHighBound(V, 1) - VarArrayLowBound(V, 1) + 1; 
    if Len=0 then begin 
     DynArraySetLength(DynArray, PDynArrayTypeInfo(TypeInfo), 1, @Len); 
     exit; 
    end; 
    end; 
    OriginalVarToDynArray(DynArray, V, TypeInfo); 
end; 

procedure FixVariants; 
var 
    VarMgr: TVariantManager; 
begin 
    GetVariantManager(VarMgr); 
    OriginalVarFromDynArray := VarMgr.VarFromDynArray; 
    VarMgr.VarFromDynArray := VarFromDynArray; 
    OriginalVarToDynArray := VarMgr.VarToDynArray; 
    VarMgr.VarToDynArray := VarToDynArray; 
    SetVariantManager(VarMgr); 
end; 

type 
    TDynamicStringArray = array of string; 

var 
    V: Variant; 
    sa: TDynamicStringArray; 
begin 
    FixVariants; 

    sa := nil; 
    V := sa; 
    sa := V; 

    Writeln(Length(sa)); 
    Readln; 
end. 
+0

की सरणी धन्यवाद। यह वास्तव में एक बड़ी बग है। –

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