确认我我写的代码问题,报错也贴上来,在程序退出的时候会报,其他时候ok
runtime error 216 at 01673ba6
内存不能为读   0*016736ab         0*01601b24等等function g_ShowStore(Const AWhereStr:string;var ARstData:TdxMemData;AMultiSelect:boolean):boolean ;
var
  strSql:string ;
  cdsQry:TClientDataSet ;
  FieldItems:TFieldItems ;
begin
  result:=false ;
  if ARstData=nil then
  ARstData:=TdxMemData.Create(nil);
  FieldItems:=TFieldItems.Create(nil) ;
  FieldItems.Sorted :=false ;
  TFrameDataAccessImpl.AddField(FieldItems,'store_code_id','store_code_id',True,false,true,80) ;
  TFrameDataAccessImpl.AddField(FieldItems,'store_code','门店代码',false,True,true,80) ;
  TFrameDataAccessImpl.AddField(FieldItems,'name','门店名称',false,True,true,120) ;
  TFrameDataAccessImpl.AddField(FieldItems,'address','地址',false,True,true,100) ;  strSql:='select store_code_id,store_code,name,address from store(nolock) ';
  if AWhereStr<>'' then
    strSql:=strSql+' where '+AWhereStr ;
  strSql:=strSql+' order by store_code ' ;
  try
    if not _Environment.DataAccess.SelectSql(strSql,cdsQry) then
    begin
      showmessage('获取门店信息出错:'+_Environment.DataAccess.LastError) ;
      exit ;
    end ;
    if cdsQry.IsEmpty then
    begin
      showmessage('没有门店信息!') ;
      exit ;
    end ;
    result:= g_ShowChoose('门店选择',cdsQry,FieldItems,ARstData,AMultiSelect,true,false) ;  finally
    cdsQry.free ;
    FieldItems.free ;
  end ;
end ;
procedure  test;
var
   RstData:TdxMemData;
begin
  RstData:=TdxMemData.Create(nil) ;
  try
    if not ShowStore(strwhere,RstData,False)then exit;  //只要不执行这句就没问题
    if RstData.RecordCount=0 then Exit;
    store_code_id:=RstData.fieldbyname('store_code_id').AsInteger;
  finally
    RstData.Free;
  end;
end;

解决方案 »

  1.   

    ShowStore过程中,跟踪一下,看看到哪报错
      

  2.   

    cdsQry:TClientDataSet ; 
    cdsQry是ClientDataSet,为何要cdsQry.Free;改为cdsQry.Close;
    if ARstData=nil then 
      ARstData:=TdxMemData.Create(nil); 
    ARstData是参数传进来的,不用Create;
      

  3.   

    关键是你在此procedure中声明了FieldItems:TFieldItems ; 
    且create之后,被TFrameDataAccessImpl所引用。虽然你在finally做了free,只是减少引用计数,对象还是存在,所以问题可能出在TFrameDataAccessImpl对此对象的管理
      

  4.   

    3楼应该是对的,按照oop的原则,不要Free对象中的子对象
    4楼的完全不知所云了,delphi中普通对象根本就没有引用计数的概念,Free也就是检查一下Self指针是不是nil,不是的话就调用 destructor TObject.Destroy 直接销毁了。interface倒是有引用计数,不过Free的话也照样销毁,delphi的destructor根本不会管interface的引用计数到没到呢
      

  5.   

    呵呵,难道我记错了?我去查查。但针对他的问题,他在创建完对象后,添加到TFrameDataAccessImpl后,又释放了,合理?
      

  6.   

    嗯是的,混淆了 -_-!他的问题应该就是TFrameDataAccessImpl得关系,因为它还记录了FieldItems的指针。虽然实体已经被释放了。在程序退出时,TFrameDataAccessImpl应该会去释放他的成员,因而出错。
      

  7.   

    function g_ShowStore(Const AWhereStr:string;var ARstData:TdxMemData;AMultiSelect:boolean):boolean ; 
    var 
      strSql:string ; 
      cdsQry:TClientDataSet ; 
      FieldItems:TFieldItems ; 
    begin 
      result:=false ; 
      if ARstData=nil then 
        ARstData:=TdxMemData.Create(nil); 
      FieldItems:=TFieldItems.Create(nil) ; 
      try //把保护移动到这里
        FieldItems.Sorted :=false ; 
        TFrameDataAccessImpl.AddField(FieldItems,'store_code_id','store_code_id',True,false,true,80) ; 
        TFrameDataAccessImpl.AddField(FieldItems,'store_code','门店代码',false,True,true,80) ; 
        TFrameDataAccessImpl.AddField(FieldItems,'name','门店名称',false,True,true,120) ; 
        TFrameDataAccessImpl.AddField(FieldItems,'address','地址',false,True,true,100) ;     strSql:='select store_code_id,store_code,name,address from store(nolock) '; 
        if AWhereStr <>'' then 
          strSql:=strSql+' where '+AWhereStr ; 
        strSql:=strSql+' order by store_code ' ; 
      
        if not _Environment.DataAccess.SelectSql(strSql,cdsQry) then 
        begin 
          showmessage('获取门店信息出错:'+_Environment.DataAccess.LastError) ; 
          exit ; 
        end ; 
        if cdsQry.IsEmpty then 
        begin 
          showmessage('没有门店信息!') ; 
          exit ; 
        end ; 
        result:= g_ShowChoose('门店选择',cdsQry,FieldItems,ARstData,AMultiSelect,true,false) ;   finally 
        cdsQry.free ; //这里释放一次 
    上一句更改为FreeAndNil(cdsQry)

        FieldItems.free ; 
      end ; 
    end ; 
    procedure  test; 
    var 
      RstData:TdxMemData; 
    begin 
      RstData:=TdxMemData.Create(nil) ; 
      try 
        if not ShowStore(strwhere,RstData,False)then exit;  //只要不执行这句就没问题 
        if RstData.RecordCount=0 then Exit; 
        store_code_id:=RstData.fieldbyname('store_code_id').AsInteger; 
      finally 
        if RstData <> nil then //加入这一句
        RstData.Free//这里释放了第二次

      end; 
    end;
      

  8.   

    if not ShowStore(strwhere,RstData,False)then exit;  //只要不执行这句就没问题 
    function g_ShowStore(Const AWhereStr:string;var ARstData:TdxMemData;AMultiSelect:boolean):boolean ;
    二個這間沒有關系吧。這到底是筆誤還是??