{ 控件动态创建的堆与栈 }

 1 procedure Form1.TestClick(Sender: TObject);
 2 var
 3   TestBtn1,BtnTemp:TButton;
 4 begin
 5 
 6   {第一步:创建一个Button,令指针TestBtn1指向这个在堆中开辟的内存区。}
 7   ////////////////////////////////////////////////////////////////////////////
 8 
 9   {NOTE:必须指定name,后面FindComponent就是通过name来找控件的,TestBtn1不是button的name}
10   TestBtn1:=TButton.Create(panel);  //让panel做此button的owner
11   with TestBtn1 do
12   begin
13     Caption:='hello';               //设置Button显示文本
14     name:= 'Button1_test';
15     left:=16;
16     top:=16;
17     =60;
18     parent:=panel;                  //让panel1做此Button的parent
19   end;
20 
21 
22   {第二步:制造内存泄漏,同时保存栈中原指针以作补救}
23   ////////////////////////////////////////////////////////////////////////////
24 
25   {保存原指针,注意此处控件名区分大小写,请务必和name属性保持完全一致}
26   btnTemp:=TButton(panel.FindComponent('Button1_test'));
27 
28   TestBtn1:=TButton.Create(panel);
29   {TestBtn1指向地址更改,从指向caption为hello的caption转为指向caption为Button2的button,
30   第一个button的指针丢失 }
31   with TestBtn1 do
32   begin
33     Caption:='Button2';
34     left:=16+70;
35     top:=16;
36     =60;
37     parent:=panel;
38   end;
39 
40   btnTemp.Caption:='world';
41   BtnTemp.Hint:='这是提示';
42   FreeAndNil(panel);                     //虽然发生内存泄漏,owner还是会负责回收,两个button和一个panel都消失
43   ShowMessage('name:'+btnTemp.name);     //name被清空
44   ShowMessage(BtnTemp.Hint);
45   try
46     if  btnTemp.Caption='world' then     //caption 仍为world,很奇怪
47     begin
48       ShowMessage('OK');
49       btntemp.Caption:='hello world';     //这是非法的,button已经回收了,会造成错误
50     end
51     else
52     begin
53       ShowMessage('crush');
54     end;
55   except
56     ShowMessage('opps!Invalid pointer.');
57   end;
58 end;
原文地址:https://www.cnblogs.com/feicaixian/p/10507180.html