我一直有一个问题总是不能解决,希望大家讨论一下:
我在做报表的时候如果吧报表的form在工程文件里面创建之后经常会碰到form会被莫名其妙的释放,而且还不是nil,报表form的所有对象都变成了nil,结果在程序中赋值得时候就会碰到非法操作,起初我以为是某一个地方不小心吧form释放了,但是我反复检查了程序,而且跟踪程序的全部过程,都没有碰到什么地方释放了空间,结果到了某一个地方后form还是会被释放,但是当我把机器重起了之后就没事了,程序运行几次之后又出现问题,始终没有解决,只好把form放在必要的地方创建,然后关闭的时候在释放,但是这个报表是经常要使用的,感觉还是放在工程文件里面创建好一些,不知道星星们有什么高见呢?
欢迎大家讨论,也许是delphi的一个自身的问题,或者是我对delphi的理解有问题,希望星星们解惑!
我的可用分也不多,只是想给大家一个讨论的机会,欢迎兄弟们进来发言!
我在做报表的时候如果吧报表的form在工程文件里面创建之后经常会碰到form会被莫名其妙的释放,而且还不是nil,报表form的所有对象都变成了nil,结果在程序中赋值得时候就会碰到非法操作,起初我以为是某一个地方不小心吧form释放了,但是我反复检查了程序,而且跟踪程序的全部过程,都没有碰到什么地方释放了空间,结果到了某一个地方后form还是会被释放,但是当我把机器重起了之后就没事了,程序运行几次之后又出现问题,始终没有解决,只好把form放在必要的地方创建,然后关闭的时候在释放,但是这个报表是经常要使用的,感觉还是放在工程文件里面创建好一些,不知道星星们有什么高见呢?
欢迎大家讨论,也许是delphi的一个自身的问题,或者是我对delphi的理解有问题,希望星星们解惑!
我的可用分也不多,只是想给大家一个讨论的机会,欢迎兄弟们进来发言!
还是自己编来的放心
var
sqlwhere:String;
account:String;
str:String;
i:integer;
postcode,yhmc,lxr,lxdh,yhdz:String;
begin
if Listbox1.Items.Count>0 then
begin
str:=Listbox1.Items[Listbox1.itemindex];
i:=pos(',',str);
account:=copy(str,1,i-1);
sqlwhere:='(ACCOUNT='''+account+''') and (KSSJ>='''+trim(edit3.text)+'000000'') and (KSSJ<='''+trim(edit4.text)+'240000'')';
//获取客户资料
dm_public.query_public.Close;
dm_public.query_public.SQL.Clear;
dm_public.query_public.SQL.Add('select * from CUSTOMER where ACCOUNT='''+account+'''');
dm_public.query_public.Open;
postcode:=dm_public.query_public.fieldbyname('POSTCODE').AsString;
yhmc:=dm_public.query_public.fieldbyname('YHMC').AsString;
lxr:=dm_public.query_public.fieldbyname('LXR').AsString;
lxdh:=dm_public.query_public.fieldbyname('LXDH').AsString;
yhdz:=dm_public.query_public.fieldbyname('YHDZ').AsString;
dm_public.query_public.Close;
//获取客户资料
//清空临时库
dm_public.Query_public.close;
dm_public.Query_public.sql.Clear;
dm_public.Query_public.SQL.Add('delete from TEMPTJ');
dm_public.Query_public.ExecSQL;
//清空临时库
//写入临时库
if (flag=2) or (flag=3) or (flag=6) then
begin
dm_public.Query_public.close;
dm_public.Query_public.sql.Clear;
dm_public.Query_public.SQL.Add('insert into TEMPTJ(ZJHM) select distinct ZJHM from THFY where'+sqlwhere);
dm_public.Query_public.ExecSQL;
end
else if (flag=4) or (flag=5) then
begin
dm_public.Query_public.close;
dm_public.Query_public.sql.Clear;
dm_public.Query_public.SQL.Add('insert into TEMPTJ(PASSWORD,ZJHM) select distinct PASSWORD,ZJHM from THFY where'+sqlwhere);
dm_public.Query_public.ExecSQL;
end;
//写入临时库
//国内话费
dm_public.Query_public.Close;
dm_public.Query_public.SQL.clear;
if (flag=2) or (flag=3) then
dm_public.Query_public.sql.add('update TEMPTJ SET GNHF=(select sum(THFY) from THFY where '+sqlwhere+' and substring(BJHM,2,1)<>''0'' and THFY.ZJHM=TEMPTJ.ZJHM)')
else if (flag=4) or (flag=5) then
dm_public.Query_public.sql.add('update TEMPTJ SET GNHF=(select sum(THFY) from THFY where '+sqlwhere+' and substring(BJHM,2,1)<>''0'' and THFY.PASSWORD=TEMPTJ.PASSWORD and THFY.ZJHM=TEMPTJ.ZJHM)')
else if (flag=6) then
dm_public.Query_public.sql.add('update TEMPTJ SET GNHF=(select sum(YSSF) from THFY where '+sqlwhere+' and substring(BJHM,2,1)<>''0'' and THFY.ZJHM=TEMPTJ.ZJHM)');
dm_public.Query_public.ExecSQL;
//国内话费
//国际话费
dm_public.Query_public.Close;
dm_public.Query_public.sql.clear;
if (flag=2) or (flag=3) then
dm_public.Query_public.sql.add('update TEMPTJ SET GJHF=(select sum(THFY) from THFY where '+sqlwhere+' and substring(BJHM,2,1)=''0'' and THFY.ZJHM=TEMPTJ.ZJHM)')
else if (flag=4) or (flag=5) then
dm_public.Query_public.sql.add('update TEMPTJ SET GJHF=(select sum(THFY) from THFY where '+sqlwhere+' and substring(BJHM,2,1)=''0'' and THFY.PASSWORD=TEMPTJ.PASSWORD and THFY.ZJHM=TEMPTJ.ZJHM)')
else if (flag=6) then
dm_public.Query_public.sql.add('update TEMPTJ SET GJHF=(select sum(YSSF) from THFY where '+sqlwhere+' and substring(BJHM,2,1)=''0'' and THFY.ZJHM=TEMPTJ.ZJHM)'); dm_public.Query_public.ExecSQL;
//国际话费
//计算总额
dm_public.Query_public.Close;
dm_public.Query_public.sql.clear;
dm_public.Query_public.sql.add('update TEMPTJ SET GNHF=0 WHERE GNHF IS NULL');
dm_public.Query_public.ExecSQL;
dm_public.Query_public.Close; dm_public.Query_public.Close;
dm_public.Query_public.sql.clear;
dm_public.Query_public.sql.add('update TEMPTJ SET GJHF=0 WHERE GJHF IS NULL');
dm_public.Query_public.ExecSQL;
dm_public.Query_public.Close; dm_public.Query_public.sql.clear;
dm_public.Query_public.sql.add('update TEMPTJ SET TOTAL=GNHF+GJHF');
dm_public.Query_public.ExecSQL;
//计算总额 dm_public.Query_public.Close;
dm_public.Query_public.SQL.Clear;
dm_public.Query_public.SQL.Add('select * from TEMPTJ order by PASSWORD,ZJHM');
dm_public.Query_public.Open; dm_public.Query1.Close;
dm_public.Query1.SQL.Clear;
dm_public.Query1.SQL.Add('select * from THFY where '+sqlwhere);
if (flag=2) or (flag=3) OR (flag=6) then//正常
dm_public.Query1.SQL.Add(' order by ZJHM,KSSJ')
else if (flag=4) or (flag=5) then
dm_public.Query1.SQL.Add(' order by PASSWORD,ZJHM,KSSJ');
dm_public.Query1.Open; if (flag=2) then//分钟
begin
frm_zjhmfz.QRLabel4.Caption:='通话时长(分)';
frm_zjhmfz.QRExpr2.Expression:='Query1.SFSJ';
end
else if flag=4 then//密码分钟
begin
frm_zjhmfz.QRLabel4.Caption:='通话时长(分)';
frm_mmfz.QRExpr2.Expression:='Query1.SFSJ';
end
else if (flag=3) then//秒
// frm_zjhmfz.QRExpr2.Expression:='FORMATNUMERIC(''0.00'',Query1.SFSJ - 1+(Query1.SJSJ/100))'
begin
frm_zjhmfz.QRLabel4.Caption:='通话时长(秒)';
frm_zjhmfz.QRExpr2.Expression:='(query1.sfsj-1)*60+query1.sjsj';
end
else if flag=5 then//密码秒
// frm_mmfz.QRExpr2.Expression:='FORMATNUMERIC(''0.00'',Query1.SFSJ - 1+(Query1.SJSJ/100))';
begin
frm_mmfz.QRLabel4.Caption:='通话时长(秒)';
frm_mmfz.QRExpr2.Expression:='(query1.sfsj-1)*60+query1.sjsj';
end; Frm_zjhm.QRLabel_POST.Caption:=postcode;
frm_zjhm.QRLabel_ZH.Caption:=account;
frm_zjhm.QRLabel_YHMC.Caption:=yhmc;
frm_zjhm.QRLabel_LXR.Caption:=lxr;
frm_zjhm.QRLabel_LXDH.Caption:=lxdh;
frm_zjhm.QRLabel_YHDZ.Caption:=yhdz;
frm_zjhm.QRLabel_start.Caption:=copy(edit3.Text,1,4)+'年'+copy(edit3.text,5,2)+'月'+copy(edit3.text,7,2)+'日';
frm_zjhm.QRLabel_end.Caption:=copy(edit4.Text,1,4)+'年'+copy(edit4.text,5,2)+'月'+copy(edit4.text,7,2)+'日'; frm_zjhmfz.qrlabel_ZH.Caption:='账号'+account;
frm_zjhm.QRLabel1.Caption:=frm_main.dwmc; Frm_mmtittle.QRLabel_POST.Caption:=postcode;
frm_mmtittle.QRLabel_ZH.Caption:=account;
frm_mmtittle.QRLabel_YHMC.Caption:=yhmc;
frm_mmtittle.QRLabel_LXR.Caption:=lxr;
frm_mmtittle.QRLabel_LXDH.Caption:=lxdh;
frm_mmtittle.QRLabel_YHDZ.Caption:=yhdz;
Frm_mmtittle.QRLabel_start.Caption:=copy(edit3.Text,1,4)+'年'+copy(edit3.text,5,2)+'月'+copy(edit3.text,7,2)+'日';
Frm_mmtittle.QRLabel_end.Caption:=copy(edit4.Text,1,4)+'年'+copy(edit4.text,5,2)+'月'+copy(edit4.text,7,2)+'日'; Frm_mmfz.QRLabel_ZH.Caption:='账号'+account;
frm_mmtittle.QRLabel1.Caption:=frm_main.dwmc; frm_true.QRLabel_ZH.Caption:='账号'+account; QRCompositeReport1.Preview;
end
else
showmessage('请重新输入客户条件!');
dm_public.Query_public.Close;
dm_public.Query1.Close;
end;
1、“跟踪程序的全部过程”,你可以跟踪这个Form是在哪个地方被释放的,就可以找到原因。
2、也可能不是Form本身的释放问题,而是在报表的打印/预览过程中某些代码出错。
就我的使用经验来说,还没有发现Delphi中有明显错误的地方,当然不排除有不够好的地方。100%(对我而言)的情况下,都是因为我自己的错误。————————————————————————————————————
宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。
————————————————————————————————————
你这样问,无疑是让大家天方夜谭阿
代码调用的部分已经贴出来了,我反复检查过其他地方的调用情况,没有地方涉及到这些form,只有这里使用,这个地方第一次进来就报错,但是重新启动后能稳定一些。
动态创建是很好,但是一次运行程序需要数百次创建和释放,感觉还是静态创建比较好一些,不知道大家都怎么处理这种情况?
Frm_mmfz frm_true Frm_mmtittle都是些什么啊?没有初始化或者创建的代码阿
if not Assigned(Frm_mmtittle) then
Frm_mmtittle:=TFrm_mmtittle.Create(Application);
\Delphi6\Demos\QuickRpt\Qr2
TOMWLD(仰首再笑天) 没有这么用过,他和application.createform(Tform,Form)有什么区别呢?
不过给楼主一个建议,您的代码不太规范,一个模块不要超过50行,如果超过了,就要考虑细化模块了.
另外您的代码中所有open和execsql的地方都没有try,这样不太好.一旦程序出错,肯定会出现一个很恶心的英文对话框.
是不是在单步调试到这里的时候,(选中frm_@@@)然后鼠标放上去会出现form;=nil的提示?
我晕!!!
我想一个稍微自负一点的程序员会如此吗
我看好象vfp之类的代码风格!!!
但是:
无论给多少钱,编程习惯还都是一样的。不明白为什么连WITH都不用。
不好意思,没能帮上什么忙!!
不过改成动态创建之后就没问有问题了,很奇怪!
流水不腐兄弟,如果别人给你的钱还不到你的成本,你会写得非常规范吗?至于with语句,我一直就不喜欢用,因为我喜欢用delphi的提示功能。这个程序原本非常简单,也就几天就搞定了,结果后来对方不断在报表上增加要求,程序一直写了3个月,最可恨的是,每天增加一些!
关于上面哪为兄弟说一个procedure不要超过50行,我也一直这样写,后来发现过程调用多了以后会一定程度上影响程序的速度,然后就在一些小程序中不在单独拆分功能了!估计这种情况肯定很多朋友都碰到过,一个小问题总也解决不了,然后就绕过去,然后慢慢就不再那么深究了问题的根本了!
Frm_mmtittle:=TFrm_mmtittle.Create(Application);这样子是先判断后创建(如果没有创建),一般application时创建的窗体是不会自动NIL的,只有退出才有.你动态创建的时候,也就是当前只有一个FORM,其它的QRLABEL也只有一个,application时创建已经有多个QRlabel,而且同名,可能会有冲突,试试看,我猜的
Frm_mmtittle:=TFrm_mmtittle.Create(Application);这样子是先判断后创建(如果没有创建),一般application时创建的窗体是不会自动NIL的,只有退出才有.你动态创建的时候,也就是当前只有一个FORM,其它的QRLABEL也只有一个,application时创建已经有多个QRlabel,而且同名,可能会有冲突,试试看,我猜的