为什么将NIL数组赋给Variant会导致在Delphi 6中返回非空数组?
发布时间:2020-12-15 09:28:22 所属栏目:大数据 来源:网络整理
导读:考虑下面的代码,在Delphi 6中编译和运行时没有错误.当我恢复动态字符串数组时,我看到的是一个长度为1的数组,其中一个元素包含一个空字符串.为什么这样,我如何安全地将NIL动态数组分配给Variant并正确恢复?这是代码: TDynamicStringArray = array of string
考虑下面的代码,在Delphi 6中编译和运行时没有错误.当我恢复动态字符串数组时,我看到的是一个长度为1的数组,其中一个元素包含一个空字符串.为什么这样,我如何安全地将NIL动态数组分配给Variant并正确恢复?这是代码:
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; 解决方法
这里有两个错误.
首先在Variants.DynArrayVariantBounds中.当动态数组为零时,这会错误地返回(0,0)的低/高边界对.它应该返回(0,-1).最新版本的Delphi中修复了此错误.这导致V:= sa返回带有单个空元素的变量数组. 第二个错误影响另一个方向,sa:= V.这个错误仍然存??在于最新版本的Delphi中.这个bug出现在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. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |