gpt4 book ai didi

delphi - SetLength/Move - 导致内存损坏

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

今天我偶然发现了一个导致我的数组损坏的问题。这是一个可重现的测试用例:

unit Unit40;

interface

type
TVertex = record
X, Y: Double;
end;

TEdge = record
V1, V2: TVertex;
end;
TEdges = array of TEdge;

type
TBoundryInfo = array of TEdges;

procedure MemoryCorrupt;

implementation

procedure MemoryCorrupt;
var
BoundryInfo: TBoundryInfo;
i, PointIndex, BoundryLength: Integer;
begin
BoundryLength := 57;
PointIndex := 0;
SetLength(BoundryInfo, BoundryLength);
for i := 0 to BoundryLength - 1 do
begin
if i <> 17 then
begin
SetLength(BoundryInfo[i], 1);
BoundryInfo[i][0].V1.X := 1;
BoundryInfo[i][0].V2.X := 1;
BoundryInfo[i][0].V1.Y := 1;
BoundryInfo[i][0].V2.Y := 1;
end else
begin
SetLength(BoundryInfo[i], 2);
BoundryInfo[i][0].V1.X := 1;
BoundryInfo[i][0].V2.X := 1;
BoundryInfo[i][0].V1.Y := 1;
BoundryInfo[i][0].V2.Y := 1;
BoundryInfo[i][1].V1.X := 1;
BoundryInfo[i][1].V2.X := 1;
BoundryInfo[i][1].V1.Y := 1;
BoundryInfo[i][1].V2.Y := 1;
end;
end;
BoundryLength := 9;
SetLength(BoundryInfo, BoundryLength);
Move(BoundryInfo[PointIndex+1], BoundryInfo[PointIndex],
((BoundryLength - 1) - PointIndex) * SizeOf(BoundryInfo[PointIndex]));
Dec(BoundryLength);
Finalize(BoundryInfo[BoundryLength]);
SetLength(BoundryInfo, BoundryLength); //After this, arrays contains garbage
BoundryInfo[0][0].V1.X := 3;
end;

end.

我猜想最后一次SetLength之后的内存损坏只是Move使用不当的症状。有人可以向我解释我做错了什么以及在这种情况下如何正确使用 Move 吗?

在最初的问题中,我在循环中从 BoundryInfo 中删除元素,这就是为什么我调用 Finalize(BoundryInfo[BoundryLength])

最佳答案

在您的代码中,

Move(BoundryInfo[PointIndex+1], BoundryInfo[PointIndex], 
((BoundryLength - 1) - PointIndex) * SizeOf(BoundryInfo[PointIndex]));

BoundryInfo[PointIndex+1] 的指针复制到 BoundryInfo[PointIndex]。该指针是另一个动态数组,您必须注意引用计数。

即:

SetLength(BoundryInfo[PointIndex],0); // release memory
Move(BoundryInfo[PointIndex+1], BoundryInfo[PointIndex],
((BoundryLength - 1) - PointIndex) * SizeOf(BoundryInfo[PointIndex]));
PPointerArray(BoundryInfo)^[BoundryLength-1] := nil; // avoid GPF

简而言之:

  • 完成在 move() 期间将被覆盖的项目;
  • 将 nil 写入最新项目,该项目由 move() 复制。

关于delphi - SetLength/Move - 导致内存损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12111061/

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