ASQLite控件的Blob类型字段内存泄漏问题

使用Delphi的ASqlite控件做Sqlite数据库的数据维护,最近打开一个大的表,总是报”out of memory while expading memory stream” 的错误,提示内存不足。

经分析,是由于ASqlite控件在默认情况下总是将数据装入内存,记录数太多时造成数据不能完整装入。经查有UniDirectional数据可是设置为单方向使用表,可以不将记录完整装入到内存。但是设置了该属性值为True后,遍历表仍然是”Out of memory while expanding memory stream” 错误,感觉没有起作用。

分析ASQlite的源码,发现其将memo类型数据当作blob类型处理,而在UniDirectional为True是,读取记录时创建的BlobStream没有释放,因此和UniDirectional为False时行为一样。

修正Bug,打开ASGSqlite3.pas,将

  1. function TASQLite3BaseQuery.GetRecord(Buffer: PAnsiChar;    GetMode: TGetMode;
  2.   DoCheck: boolean): TGetResult;

函数的末尾部分

  1.     if Result = grOK then
  2.     begin
  3.       if FUniDir then begin
  4.           ptr := Connection.SQLite3_GetNextResult(Connection.DBHandle, FStatement, FParams,self);
  5.           if ptr <> nil then begin
  6.              Move(ptr^, ActiveBuffer^, MaxStrLen);
  7.           end else Result := grEOF;
  8.       end else begin
  9.           ptr := FResult.GetData(FCurRec);
  10.           if FResult.Count = 0 then
  11.              InternalInitRecord(Buffer)
  12.           else
  13.              if ptr <> nil then Move(ptr^, Buffer^, MaxStrLen); // albert 17/11/2004
  14.       end;
  15.       …

修改为

  1.     if Result = grOK then
  2.     begin
  3.       if FUniDir then begin
  4.           // 增加部分,释放前一记录的blobstream内存
  5.           if FResult.Count > 0 then begin FResult.FreeBlobs; FResult.Delete(0); end;
  6.          
  7.           ptr := Connection.SQLite3_GetNextResult(Connection.DBHandle, FStatement, FParams,self);
  8.           if ptr <> nil then begin
  9.              FResult.Add(ptr, 0);  // 增加部分,当前行添加到缓存中,等待下次释放
  10.              Move(ptr^, ActiveBuffer^, MaxStrLen);
  11.           end else Result := grEOF;
  12.       end else begin
  13.           ptr := FResult.GetData(FCurRec);
  14.           if FResult.Count = 0 then
  15.              InternalInitRecord(Buffer)
  16.           else
  17.              if ptr <> nil then Move(ptr^, Buffer^, MaxStrLen); // albert 17/11/2004
  18.       end;
  19.      …

修改后编译程序,再次打开库文件遍历表,没有再次出现问题。

Popularity: 4% [?]

Related

Comments

Leave a Reply