请问一个类变量在使用前是否必须要创建?
比如说
function Add(client:TClientInfo):boolean;
var
tmpClient:TClientInfo;
begin
tmpClient := client; //这里使用对不对?是否一定要
//运行tmpClient := TClientInfo.Create后才能用?
end;
比如说
function Add(client:TClientInfo):boolean;
var
tmpClient:TClientInfo;
begin
tmpClient := client; //这里使用对不对?是否一定要
//运行tmpClient := TClientInfo.Create后才能用?
end;
解决方案 »
- 如果查询范围内数据不全怎么办?
- 关于Hook钩子函数获得窗口实例
- 怎样可以使能预览时显示的内容 而打印时可以不打印?
- delphi的前途(钱途)?
- ADOQUERY控件使用,急!!!!!!!!!!
- 有打算从delphi改到java的吗,进来讨论一下~
- delphi里自己写的procedure和function要怎么声明一下才可以用呀?
- 客户机向主机上传,删除文件?相当于Romote Administrator的程序!
- 记录型二进制文件如何从中删除指定记录??
- 如何编写类似Treeview结构的目录选取对话框,或者有这方面的VCL吗?份是不多,望大哥赐教
- 初用TreeView,一下子找不到有关使用的资料,Help
- socket的基础问题
var
tmpClient:TClientInfo;
begin
tmpClient := client; //这里使用对不对?是否一定要'
//可以的因为
//参数client:TClientInfo实际为一个指针,
//运行tmpClient := TClientInfo.Create后才能用?
//如果这样的话一定要使用完以后FREE否则要有泄露
end;
并且会出现泄露
function TClientList.GetcommaText :string;
var
tmpClient:TClientInfo;
begin
Result:='';
if fHead = nil then Exit;
tmpClient := fHead;
if fMutex.GetObject Then
begin
while (tmpClient.fNextClient <> fHead ) do ///此行总是报错,请看以下注释
begin
Result:=Result + tmpClient.UserInfo.Name+'_ID='+inttostr(tmpClient.ClientID)+',';
tmpClient := tmpClient.fNextClient;
end;
Result := Result + tmpClient.UserInfo.Name+ '_ID='+inttostr(tmpClient.ClientID);
fMutex.ReleaseObject;
end;
end;
///注释
TClientInfo = class
...
...
Prev,Next:TClientInfo;
end;
这里fHead是一个TClientInfo的结构,内部还有两个Next,Prev都是指向TClientInfo结构的变量,用来做双向链表。
加入结点是这样做的:函数传递一个clientinfo:TClientInfo结构的变量,是已建好的,并且有数据。函数中定义一个tmpClient:TCLientInfo,并创建,然后把clientInfo的数据全部拷贝到tmpClient中。判断fHead是否为空,为空则fHead指向tmpClient,并把Prev和Next都指向fHead。不为空则加到后面。
如下:
//<--------------------------------------------->
//<-----------添加新结点------------------------>
//<--------------------------------------------->
{ TClientList public Add }
function TClientList.Add(client:TClientInfo;inds:PInteger=nil):boolean;
var
tmpClient:TClientInfo;
ids:integer;
begin
Result := false;
if client = nil then Exit;
//获取全局唯一标识符
if not fIndexs.Assign(@ids) then Exit; //分配标识符
client.fClientID := ids;
if inds <> nil then inds^:=ids; //返回标识符值
tmpClient := TClientInfo.Create;
tmpClient.Assign(client); //复制client所有值到tmpClient
if fMutex.GetObject then //抢占互斥
begin
if fHead = nil then
begin
fHead := tmpClient;
fHead.fNextClient := fHead;
fHead.fPrevClient := fHead;
end
else
begin
fHead.fPrevClient.fNextClient := tmpClient;
tmpClient.fPrevClient := fHead.fPrevClient;
fHead.fPrevClient := tmpClient;
tmpClient.fNextClient := fHead;
end;
fMutex.ReleaseObject; //释放互斥
Result:=true;
if Assigned(fOnListChange) then
fOnListChange(self);
end
else
tmpClient.Free; //如果抢夺互斥不成功,则放弃添加。
end;添加过程没有发生过问题,不知道代码方面是否还有其它错误。但上面的GetCommaText的那一行总是报错。
我的程序其实是这样的:当有客户连入时,获取客户信息后加入ClientList中,fHead是ClientList的一个私有成员。属于TClientInfo类变量。也就是当有客户连入时,就发生了GetCommaText里的错误。但令我不解的是,我用按钮模拟生成客户加入时就没有任何问题了。
procedure TClientList.Delete(clientID:integer);
var
tmpClient:TClientInfo;
tmpPrev:TClientInfo;
tmpNext:TClientInfo;
ids:integer;
begin
if clientID <0 then Exit;
if Pointer(fHead) = nil then Exit;
if fMutex.GetObject then
begin
tmpClient := fHead;
ids:=tmpClient.fClientID; //保存标识符以便稍后释放
//查找结点位置
while (tmpClient.fNextClient <> fHead) and (tmpClient.fClientID <> clientID) do
tmpClient := tmpClient.fNextClient;
//删除
if tmpClient.fClientID = clientID then
begin
tmpPrev:=tmpClient.fPrevClient;
tmpNext:=tmpClient.fNextClient;
if tmpClient = fHead then
begin
fHead := tmpNext;
end;
tmpPrev.fNextClient := tmpNext;
tmpNext.fPrevClient := tmpPrev; //执行到这里就出问题了。
tmpPrev:=nil;
tmpNext:=nil;
FreeAndNil(tmpClient); //标注2 end;
//释放互斥和标识符
fMutex.ReleaseObject;
fIndexs.Release(ids);
//触发事件
if Assigned(fOnListChange) then
fOnListChange(self);
end;
end;
当结点只有一个时,删除过程中,执行到上面的地方时,监视窗口里显示出tmpNext和tmpPrev是inaccessible due to optimization,而且下面两句未执行就跳到标注2了。
当执行到标注2结束时,发现fHead仍然有值,但其中有一个指向TUserInfo类的结构地址发生了变化。按我的意思,应该是:由于只有一个结点,故不管怎么样,tmpClient总是指向fHead的,执行标注2后类被释放,fHead应该不再有值的。为什么还会有值,而且值有部分发生了变化?