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,将
-
function TASQLite3BaseQuery.GetRecord(Buffer: PAnsiChar; GetMode: TGetMode;
-
DoCheck: boolean): TGetResult;
函数的末尾部分
-
if Result = grOK then
-
begin
-
if FUniDir then begin
-
ptr := Connection.SQLite3_GetNextResult(Connection.DBHandle, FStatement, FParams,self);
-
if ptr <> nil then begin
-
Move(ptr^, ActiveBuffer^, MaxStrLen);
-
end else Result := grEOF;
-
end else begin
-
ptr := FResult.GetData(FCurRec);
-
if FResult.Count = 0 then
-
InternalInitRecord(Buffer)
-
else
-
if ptr <> nil then Move(ptr^, Buffer^, MaxStrLen); // albert 17/11/2004
-
end;
-
…
修改为
-
if Result = grOK then
-
begin
-
if FUniDir then begin
-
// 增加部分,释放前一记录的blobstream内存
-
if FResult.Count > 0 then begin FResult.FreeBlobs; FResult.Delete(0); end;
-
-
ptr := Connection.SQLite3_GetNextResult(Connection.DBHandle, FStatement, FParams,self);
-
if ptr <> nil then begin
-
FResult.Add(ptr, 0); // 增加部分,当前行添加到缓存中,等待下次释放
-
Move(ptr^, ActiveBuffer^, MaxStrLen);
-
end else Result := grEOF;
-
end else begin
-
ptr := FResult.GetData(FCurRec);
-
if FResult.Count = 0 then
-
InternalInitRecord(Buffer)
-
else
-
if ptr <> nil then Move(ptr^, Buffer^, MaxStrLen); // albert 17/11/2004
-
end;
-
…
修改后编译程序,再次打开库文件遍历表,没有再次出现问题。
Popularity: 7% [?]