delphi – 压缩和发送TFDDataset数据后释放表单时的AV
我在发布表单时有一个AV,它在我压缩并将FireDAC数据集的数据发送到远程服务器时出现.
这是我用来压缩TFDDataset数据的代码: function CompressDataset(Dataset: TFDDataset): TMemoryStream; var Data: TMemoryStream; Compress: TZCompressionStream; begin Result := TMemoryStream.Create; Data := TMemoryStream.Create; try Compress := TZCompressionStream.Create(Result); Dataset.SaveToStream(Data,TFDStorageFormat.sfBinary); Data.Position := 0; Compress.CopyFrom(Data,Data.Size); finally Data.Free; Compress.Free; end; Result.Position := 0; end; 这是将压缩数据发送到远程调用(Datasnap)的代码. procedure TfrmRentFacturacion_Facturar.btnSendDesgloseClick(Sender: TObject); var Stream: TMemoryStream; begin if qryFacturacion_Desglose.State = dsEdit then qryFacturacion_Desglose.Post; Stream := CompressDataset(qryFacturacion_Desglose); try spActualizaDesglose.ParamByName('AStream').AsStream := Stream; spActualizaDesglose.ExecProc; finally Stream.Free; end; end; 这段代码留下了一些不稳定的东西,很可能是TFDDataset qryFacturacion_Desglose,并在释放表单时引发AV.但我没有得到可能出错的东西. PS:感谢@J …建议检查调用堆栈我找到了问题的根源.这是调用堆栈: :000000000040E735 TObject.Free + $15 :00000000007F1123 TParamObject.Destroy + $43 :000000000041A155 TInterfacedObject._Release + $55 :000007FEFF2211CE ; C:Windowssystem32oleaut32.dll :0000000000459DAB VarClearDeep + $1B :0000000000459E6B @VarClear + $1B :0000000000459E7D @VarClr + $D :00000000004149F4 @VarClr + $14 :0000000000414ACC @FinalizeArray + $BC :00000000004162F1 @DynArrayClear + $61 :0000000000414B58 @FinalizeArray + $148 :0000000000414985 @FinalizeRecord + $75 :000000000040E82E TObject.CleanupInstance + $4E :000000000040E450 TObject.FreeInstance + $10 :000000000040F1C1 @ClassDestroy + $11 :000000000051ED43 TCollectionItem.Destroy + $43 :000000000040E738 TObject.Free + $18 :000000000051F40A TCollection.Clear + $5A :000000000051F1CD TCollection.Destroy + $2D :000000000084A858 TFDParams.Destroy + $88 :0000000000838FD8 FDFree + $18 :000000000084A8BB TFDParams.RemRef + $2B :0000000000B8C907 TFDCustomCommand.Destroy + $57 :000000000040E738 TObject.Free + $18 :00000000005419F3 TComponent.DestroyComponents + $93 :000000000054117F TComponent.Destroy + $2F :0000000000B92A66 TFDCustomTableAdapter.Destroy + $86 :0000000000B9BE02 TFDRdbmsDataSet.Destroy + $C2 :000000000040E738 TObject.Free + $18 :00000000005419F3 TComponent.DestroyComponents + $93 :000000000054117F TComponent.Destroy + $2F :00000000006039C2 TControl.Destroy + $192 :000000000060AA91 TWinControl.Destroy + $1B1 :0000000000797273 TScrollingWinControl.Destroy + $73 :0000000000798EB7 TCustomForm.Destroy + $1E7 :000000000040E738 TObject.Free + $18 :00000000007A1389 TCustomForm.CMRelease + $9 :000000000040EE81 TObject.Dispatch + $41 :0000000000607D56 TControl.WndProc + $386 :000000000060EC07 TWinControl.WndProc + $8E7 :000000000079ADB0 TCustomForm.WndProc + $910 :000000000060DE4C TWinControl.MainWndProc + $2C :0000000000545056 StdWndProc + $26 :00000000777D9BBD ; C:Windowssystem32USER32.dll :00000000777D98C2 ; C:Windowssystem32USER32.dll :00000000007A8E84 TApplication.ProcessMessage + $134 :00000000007A8EF8 TApplication.HandleMessage + $18 :00000000007A9364 TApplication.Run + $F4 Impuestos.Impuestos :00000000776B59CD ; C:Windowssystem32kernel32.dll :00000000778EA561 ; ntdll.dll 尝试释放执行对Datasnap Server的远程调用的spActualizaDesglose TFDStoredProc的参数AStream时,会发生AV. 我已经更改了呼叫,因此在执行远程呼叫后它不会释放原始数据流. procedure TfrmRentFacturacion_Facturar.btnSendDesgloseClick(Sender: TObject); var Stream: TMemoryStream; begin if qryFacturacion_Desglose.State = dsEdit then qryFacturacion_Desglose.Post; Stream := CompressDataset(qryFacturacion_Desglose); spActualizaDesglose.ParamByName('AStream').AsStream := Stream; spActualizaDesglose.ExecProc; end; 现在表单发布没有问题,但这是正确的吗?,我不会有内存泄漏吗? 谢谢. 解决方法
从
the manual page开始:
强调我的.所以是的,将流分配给参数会给出该流的参数所有权,并且当它自身被释放时它负责释放它(当数据集被拥有数据集组件的表单释放时由数据集完成). 当你在这里释放流: Stream := CompressDataset(qryFacturacion_Desglose); try spActualizaDesglose.ParamByName('AStream').AsStream := Stream; spActualizaDesglose.ExecProc; finally Stream.Free; end; 您正在销毁参数持有引用的对象,并且当参数对象尝试第二次释放它时它会引发AV. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |