gpt4 book ai didi

delphi - 为什么在 Delphi 6 中将 NIL 数组分配给 Variant 会导致返回非空数组?

转载 作者:行者123 更新时间:2023-12-03 15:11:29 26 4
gpt4 key购买 nike

考虑下面的代码,它在 Delphi 6 中编译和运行时没有错误。当我恢复动态字符串数组时,我在 sa 中看到的不是一个空数组,而是一个长度为 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中。当动态数组为 nil 时,会错误地返回 (0, 0) 的下/高界对。它应该返回(0, -1)。这个错误在最新版本的 Delphi 中已得到修复。这会导致 V := sa 返回带有单个空元素的变体数组。

第二个错误影响另一个方向,sa := V。这个错误在最新版本的 Delphi 中仍然存在。此错误位于 Variants.DynArrayFromVariant 中。有一个重复/直到循环遍历输入变量数组并填充输出动态数组。当输入变体数组为空时,它不应进入 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.

关于delphi - 为什么在 Delphi 6 中将 NIL 数组分配给 Variant 会导致返回非空数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12830822/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com