求助:一个非常奇怪的问题,用了 dipose() ,反而不行了,这是为什么啊?谢谢! ( 积分: 50 )

  • 主题发起人 主题发起人 宇宙神
  • 开始时间 开始时间

宇宙神

Unregistered / Unconfirmed
GUEST, unregistred user!
unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
TreeView1: TTreeView;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
ss:string;
ss1:^string;
begin
ss:='12345';
new(ss1);
ss1^:=ss;
TreeView1.Items[1].Data:=ss1;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
CurrenNode:TTreeNode;
Ipvalue:^string;
Ipvaluestr:string;
begin

CurrenNode:=treeview1.Items[1];
new(Ipvalue);
try
Ipvalue:=CurrenNode.Data;
Ipvaluestr:=Ipvalue^;
finally
dispose(Ipvalue);
end;
showmessage(Ipvaluestr);
end;

end.


现在问题是:
我单击一次 Button1 ,show 出 字符串 12345
我再次单击,就出现错误了,是地址路径错的那种

如果,我写

procedure TForm1.Button1Click(Sender: TObject);
var
CurrenNode:TTreeNode;
Ipvalue:^string;
Ipvaluestr:string;
begin

CurrenNode:=treeview1.Items[1];
new(Ipvalue);
Ipvalue:=CurrenNode.Data;
Ipvaluestr:=Ipvalue^;

showmessage(Ipvaluestr);
end;


则没有错误,这是什么原因啊?

谢谢!
 
string本身就是个指针,编译器管理内存,不需要分配和释放内存空间。
 
procedure TForm1.Button1Click(Sender: TObject);
var
CurrenNode:TTreeNode;
Ipvalue:^string;
Ipvaluestr:string;
begin

CurrenNode:=treeview1.Items[1];
new(Ipvalue);//这个可以注销,没用
try
Ipvalue:=CurrenNode.Data;//这个直接把地址ss1赋值过来了
Ipvaluestr:=Ipvalue^;
finally
dispose(Ipvalue); //释放后,ss1内存没有了,即treeview1.Items[1]中就没地址数据了,所以在次释放时就会出错了。
end;
showmessage(Ipvaluestr);
end;
//我感觉是这个原因
 
而且你dispose(Ipvalue);释放的并不是new(Ipvalue);分配的空间,因为中间你把ss1的空间地址赋给Ipvalue了,所以new(Ipvalue)还会浪费内存。而ss1也只能释放一次,所以你再次释放时出错了
 
1。FormCreate里的ss是局部变量,你把改为全局或者私有
2。Button1Click里的IpValue不需要New,可以直接赋值,如果要Dispose,只能释放一次,除非重新New一次申请内存
3。New和Dispose要对应,FormCreate申请的,可以在FormDestroy里释放
 
procedure TForm1.Button1Click(Sender: TObject);
var
CurrenNode:TTreeNode;
Ipvalue:^string;
Ipvaluestr:string;
begin

CurrenNode:=treeview1.Items[1];
new(Ipvalue);
//你建立一个IPValue的指针,并分配了空间
try
Ipvalue:=CurrenNode.Data;
// 你建立一个IPValue的指针,和你要的节点指向同一个地方,也就是说
Ipvaluestr:=Ipvalue^;
finally
dispose(Ipvalue);
// 你现在是不是把Data释放了,明白?
end;
showmessage(Ipvaluestr);
end;
 
谢谢各位大哥!
那我的程序要怎么改啊?

要在什么地方释放呢?
 
都不知你要实现什么功能,不知你要成什么样,如果只是为了可以点击多次的话,那么可以这样:
procedure TForm1.Button1Click(Sender: TObject);
var
CurrenNode:TTreeNode;
Ipvalue:^string;
Ipvaluestr:string;
begin

CurrenNode:=treeview1.Items[1];
//new(Ipvalue); //取消这一行
Ipvalue:=CurrenNode.Data;
Ipvaluestr:=Ipvalue^;

showmessage(Ipvaluestr);
end;

在此注销:
procedure Tcaws.FormDestroy(Sender: TObject);
var
CurrenNode:TTreeNode;
Ipvalue:^string;
begin
CurrenNode:=treeview1.Items[1];
Ipvalue:=CurrenNode.Data;
dispose(Ipvalue);
end;
 
谢谢大哥:
new(Ipvalue); //申请空间
Ipvaluestr:='12345';
try
Ipvalue^:=Ipvaluestr;
CurrenNode:=TreeView1.Items[0];//当前节点为根节点
NewNode:=TreeView1.Items.AddChild(CurrenNode,'工作站'); //增加子节点
NewNode.Data:=Ipvalue;
finally
// dispose(Ipvalue); //释放指针
end;


我这种情况如果没有 new(Ipvalue);
则编译错误啊?
那这要怎么办呢?

我别的地方还需要用 NewNode.Data

谢谢!
 
你new之后有立即dispose,有什么意思?
正确的释放方法:
在TTreeView的OnDeletion事件中
If Node.date <> nil Then
dispoes(Node.date)
 
再给你一个文章,对你解决这个问题有很大的帮助。
delphi中TreeView使用常见问题
编程心得
1,在Delphi中,TreeView控件是一款很出色而且很常用的控件。
在使用过程中,了解到其TTreeNode对象的data属性存储相关数据很有用,一般情况下,我们先声明一个结构体以及其指针,例如:
type
PMyRc = ^TMyRc;
TMyRc = Record
id:string;
name:string;
age:integer;
end;

添加一个节点,显示信息为TMyRc的name,同时存储id,age。方法如下:
var
p:PMyRc;
i:integer;
begin
Randomize;
for i:= 0 to 9 do
begin
New(p);
p.id:=inttostr(random(100));
p.name:='name'+ inttostr(random(205));
p.age:=random(90);
// Caption := p.id+' '+P.name + ' '+inttostr(p.age);
TreeView1.Items.AddObject(nil,p.name,Tobject(p));
//dispose(p); 如果在这里释放指针,id,age并不能存在树中,而是在这里就被释放了。应该在释放树的事件里书写。
end;
end;

释放树的事件deletion, 即使是删除也会执行这些代码。所以不用担心内存泄漏。但是如果不书写以下代码,或者用相关的方式释放内存,必定会造成内存泄漏。
procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
dispose(pmyrc(node.data));
end;

访问某个树枝中的age值:
Pmyrc(TreeView1.Selected.data)^.age
 
后退
顶部