这不是关于深拷贝或克隆对象的问题,因为已经有数百万的对象,尽管事实上这就是我一开始就在寻找自己的事实,如果这是我唯一的选择,请重新登录。但似乎没有必要像这样简单的事情过分复杂。泄漏内存,释放对象和对象“复制”
我一直在翻译一些C++代码到德尔福,基本上公然使用SDL根据this复制俄罗斯方块。这对SDL来说是一次学习体验,但现在也是以Delphi的方式。我正在链接到具有我无法完全翻译的代码的特定页面。游戏按预期工作,但有一点我必须切换当前正在下降的区块,并将其正方形添加到底部的其他区块,然后将下一个区块设置为当前正在下降的区块。
下面是我的一些代码,没有太多复制:TSingleSquare
,TBlock
和ChangeFocusBlock
程序。
TSingleSquare = class
private
S_TextureSurf: pSDL_SURFACE;
S_BlockType: TBlockType;
S_CenterX, S_CenterY: integer;
public
constructor Create(CX, CY: integer; T: pSDL_SURFACE; BT: TBlockType);
destructor Destroy; override;
procedure Draw(W: pSDL_SURFACE);
procedure Move(D: TDirection);
function GetCenterX: integer;
function GetCenterY: integer;
procedure SetCenterX(lX: integer);
procedure SetCenterY(lY: integer);
end;
Ttmp_ar = array of integer;
TSquaresArray = array of TSingleSquare;
TBlock = class
private
B_CenterX, B_CenterY: integer;
B_BlockType: TBlockType;
B_SquaresArray: TSquaresArray;
B_TextureSurf: pSDL_SURFACE;
public
constructor Create(CX, CY: integer; TS: pSDL_SURFACE; BT: TBlockType);
destructor Destroy; override;
procedure SetupSquares(SX, SY: integer);
procedure Draw(W: pSDL_SURFACE);
procedure Move(D: TDirection);
procedure Rotate;
function GetRotatedSquares: Ttmp_ar;
function GetSquaresArray: TSquaresArray;
function GetBlockType: TBlockType;
end;
procedure ChangeFocusBlock;
var
Square_ar: TSquaresArray;
i: integer;
begin
Square_ar := g_FocusBlock.GetSquaresArray
SetLength(g_OldSquares, (Length(g_OldSquares) + Length(Square_ar)));
for i := Low(Square_ar) to High(Square_ar) do
begin
g_OldSquares[i+Length(g_OldSquares)-Length(Square_ar)] := Square_ar[i];
Square_ar[i] := nil;
end;
g_FocusBlock := nil;
g_FocusBlock := g_NextBlock;
g_NextBlock := nil;
g_FocusBlock.SetupSquares(BLOCK_START_X, BLOCK_START_Y);
g_NextBlock := TBlock.Create(NEXT_BLOCK_CIRCLE_X, NEXT_BLOCK_CIRCLE_Y, GameBitmap, TBlockType(Random(11)));
end;
我知道我不是释放g_FocusBlock
而这正是我的内存泄漏,但我不能找到一个合适的位置,以释放它摆在首位,如果我离开它这样,内存泄漏是我唯一的问题。一旦我开始寻找解决方案,当我尝试迭代g_OldSquares
并且我明白为什么时,它会在我屁股后面咬我,然后方块仍然指向应该释放的g_FocusBlock
方块。当我在每一步添加断点并观察数值发生了什么时,我会感到困惑,在g_FocusBlock
被释放后,我将它设置为g_NextBlock
并创建一个新的下一个块后,所有内容都按g_OldSquares
顺序排列。然而,后来迭代g_OldSquares
我注意到,部分正方形正在被覆盖,因为在内存得到重用?我突然不能相信Watchlist的值是真的?
这段文字的底线是,我想了解g_OldSquares
发生了什么,以及为什么它的值不会改变,即使通过监视列表检查时地址是相同的。
但更重要的是什么才是正确的行动,以使其正常工作?我知道使用TPersistent
并覆盖它的Assign
是为了能够在对方之间真正地分配对象(尽管我不完全确定如何完成这个任务),但在这里我仍然必须摆脱“链接”或在g_OldSquares
和g_FocusBlock
之间共享内存(我对任何不正确使用的单词表示歉意,我并不真正流利地使用编程),以便能够释放后者。
让羞耻开始。
编辑:当我做这个
for i := Low(g_OldSquares) to High(g_OldSquares) do
begin
row := (g_OldSquares[i].GetCenterY - top) div row_size;
Inc(squares_in_row[row])
end;
constructor TBlock.Create(CX, CY: integer; TS: pSDL_Surface; BT: TBlockType);
var
i: integer;
begin
B_CenterX := CX;
B_CenterY := CY;
B_BlockType := BT;
B_TextureSurf:= TS;
case BT of
SQUARE_BLOCK..REVERSE_S_BLOCK: SetLength(B_SquaresArray, 4);
STRAIGHT_TRI_BLOCK..BENT_TRI_BLOCK: SetLength(B_SquaresArray, 3);
TWO_BLOCK: SetLength(B_SquaresArray, 2);
DOT_BLOCK: SetLength(B_SquaresArray, 1);
end;
SetupSquares(CX, CY);
end;
destructor TBlock.Destroy;
var
i: integer;
begin
for i := Low(B_SquaresArray) to High(B_SquaresArray) do
B_SquaresArray[i].Free;
inherited;
end;
您可以查看“TInterrfacedObject”http://en.wikipedia.org/wiki/Reference_counting –
您可以创建一个对象并对其进行引用。然后,稍后,您放弃对该目标的引用,并使引用指向另一个对象。正是在这一点上,就在你放弃物体之前,你需要释放它。是的,使用接口进行自动引用计数可以完成这项工作。 –
如果没有任何其他链接到对象(如果你说关于内存泄漏,那么可能没有)然后'g_FocusBlock:= nil;'可能是删除最后一个链接,因此应该替换为'g_FocusBlock.Free '。但是,如果你使用引用计数的内存模型,那么'g_FocusBlock:= nil;'会(这是最后一个指针)真正为你释放对象。 –