动态数组 && 释放问题

理论上,数组的容器就是进程,关闭程序,数组的那块才会释放掉。不像类(如窗体上的的按钮设置了容器即parent,它放在谁的上面,谁在释放之前就会把按钮先释放掉),类的对象有parent、owner这两个的一个就会跟着parent或者owner释放而释放。

直接释放一维会造成内存泄露。setlength了几次就要释放几次!第一个setlength是一维给了一次,二维又setlength给了一次,释放就反过来,先把二维释放,再释放一维。怎么给的空间,就怎么把空间释放掉,不要给程序留下隐患。

但是,测试发现,先释放二维再释放一维与直接释放一维,这二者的效果是一样的(看下面代码的最后2个button的过程代码即可)!!以后对于多维数组的释放问题,直接释放一维数组即可!

释放动态数组可使用下面这3种方式,都可以实现:

SetLength(Myarray,0);
Finalize(Myarray);
Myarray:=nil;

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Array_01_static: TButton;
    Array_01_dynamic: TButton;
    Array_02_static: TButton;
    Array_02_dynamic: TButton;
    Memo1: TMemo;
    Button1: TButton;
    procedure Array_01_staticClick(Sender: TObject);
    procedure Array_01_dynamicClick(Sender: TObject);
    procedure Array_02_staticClick(Sender: TObject);
    procedure Array_02_dynamicClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    myarray02_02:array of array of string;//定義動態二維數組
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Array_01_staticClick(Sender: TObject);
var
  myarray01_01:array[0..2] of string;
  i:Integer;
begin
  //myarray01_01[0]:='0_A';
  //myarray01_01[1]:='1_A';
  //myarray01_01[2]:='2_A';
  for i:=Low(myarray01_01) to High(myarray01_01)  do
  begin
    myarray01_01[i]:=IntToStr(i)+'_A';
  end;
  Memo1.Clear;
  for i:=Low(myarray01_01) to High(myarray01_01)  do
  begin
    Memo1.Lines.Add('i=  '+IntToStr(i)+' Value: '+myarray01_01[i]);
  end;
end;

procedure TForm1.Array_01_dynamicClick(Sender: TObject);
var
  myarray01_02:array of string;
  i:Integer;
begin
  SetLength(myarray01_02,3);
  for i:=Low(myarray01_02) to High(myarray01_02)  do
  begin
    myarray01_02[i]:=IntToStr(i)+'_B';
  end;
  Memo1.Clear;
  for i:=Low(myarray01_02) to High(myarray01_02)  do
  begin
    Memo1.Lines.Add('i=  '+IntToStr(i)+' Value: '+myarray01_02[i]);
  end;
  SetLength(myarray01_02,0); //釋放數組空間
end;

procedure TForm1.Array_02_staticClick(Sender: TObject);
var
  myarray02_01:array [0..2]of array [0..3]of string;//定義靜態二維數組
  i,j,n:Integer;
begin
  n:=0;
  for i:=Low(myarray02_01) to High(myarray02_01) do
  begin
    for j:=Low(myarray02_01[i]) to High(myarray02_01[i]) do
    begin
      Inc(n);
      myarray02_01[i][j]:=IntToStr(n)+'_C'
    end;
  end;

  Memo1.Clear;
  for i:=Low(myarray02_01) to High(myarray02_01) do
  begin
    for j:=Low(myarray02_01[i]) to High(myarray02_01[i]) do//注意,這裡是針對每個第一維元素里面包含的第二維元素的循環!
    begin
      Memo1.Lines.Add('i=  '+IntToStr(i)+ ' j=  '+IntToStr(j)+' Value: '+myarray02_01[i][j]);
    end;
  end;

end;

procedure TForm1.Array_02_dynamicClick(Sender: TObject);
var
  //myarray02_02:array of array of string;//定義動態二維數組
  i,j,n:Integer;
begin
  n:=0;
  SetLength(myarray02_02,100);

  for i:=Low(myarray02_02) to High(myarray02_02) do
  begin
    SetLength(myarray02_02[i],100);//給每個一維元素分配5個二維空間(即每個一維元素裡面都有5個元素)
  end;
  for i:=Low(myarray02_02) to High(myarray02_02) do
  begin
    for j:=Low(myarray02_02[i]) to High(myarray02_02[i]) do//針對每個第一維元素里面包含的第二維元素的循環
    begin
      Inc(n);
      myarray02_02[i][j]:=IntToStr(n)+'_D'
    end;
  end;

  Memo1.Clear;
  for i:=Low(myarray02_02) to High(myarray02_02) do
  begin
    for j:=Low(myarray02_02[i]) to High(myarray02_02[i]) do
    begin
      Memo1.Lines.Add('i=  '+IntToStr(i)+ ' j=  '+IntToStr(j)+' Value: '+myarray02_02[i][j]);
    end;
  end;
  {
  for i:=Low(myarray02_02) to High(myarray02_02) do
  begin
    SetLength(myarray02_02[i],0);//先釋放二維裡的空間
  end;

  SetLength(myarray02_02,0);//再釋放一維的空間
  } //這裡真的有必要釋放2次嗎?把這2句代碼拿出來放到按鈕里對比測試一下看下效果~~
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  i:Integer;
begin
  //這裡為了說明有無必要釋放2次,先2次釋放一起運行一遍,然後再注釋掉第1次釋放的之後
  //再運行,同時打開工作管理員,選擇‘處理程序’頁,找到當前運行的exe,對比看看
  //該exe的‘記憶體(私人工作集)’的2次運行有啥差別。
  {for i:=Low(myarray02_02) to High(myarray02_02) do
  begin
    SetLength(myarray02_02[i],0);//先釋放二維裡的空間
  end;
  }
  SetLength(myarray02_02,0);//再釋放一維的空間
  //事實證明,先釋放二維再釋放一維和直接釋放一維的效果一樣!調試時也能看到2種釋放
  //方式之後數組里的值都會被清空!
end;

end.

 form窗体代码:

object Form1: TForm1
  Left = 417
  Top = 394
  Width = 511
  Height = 234
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Array_01_static: TButton
    Left = 3
    Top = 38
    Width = 117
    Height = 25
    Caption = 'Array_01_static'
    TabOrder = 0
    OnClick = Array_01_staticClick
  end
  object Array_01_dynamic: TButton
    Left = 4
    Top = 96
    Width = 118
    Height = 25
    Caption = 'Array_01_dynamic'
    TabOrder = 1
    OnClick = Array_01_dynamicClick
  end
  object Array_02_static: TButton
    Left = 376
    Top = 38
    Width = 103
    Height = 25
    Caption = 'Array_02_static'
    TabOrder = 2
    OnClick = Array_02_staticClick
  end
  object Array_02_dynamic: TButton
    Left = 376
    Top = 98
    Width = 106
    Height = 25
    Caption = 'Array_02_dynamic'
    TabOrder = 3
    OnClick = Array_02_dynamicClick
  end
  object Memo1: TMemo
    Left = 132
    Top = 4
    Width = 231
    Height = 144
    ImeName = '中文(?体) - 搜狗拼音?入法'
    Lines.Strings = (
      'Memo1')
    ScrollBars = ssBoth
    TabOrder = 4
  end
  object Button1: TButton
    Left = 393
    Top = 141
    Width = 75
    Height = 25
    Caption = '釋放'
    TabOrder = 5
    OnClick = Button1Click
  end
end
原文地址:https://www.cnblogs.com/168-h/p/15247625.html