2017-03-23 86 views
5

我在發佈表單時有一個AV,當我壓縮並將FireDAC數據集的數據發送到遠程服務器時,它會出現。AV在壓縮併發送TFDDataset的數據後發佈表單

這是我使用壓縮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 ...建議檢查調用堆棧我發現問題的根源。這是調用堆棧:試圖釋放spActualizaDesglose TFDStoredProc的參數AStream執行到DataSnap服務器的遠程調用時出現

:000000000040E735 TObject.Free + $15 
:00000000007F1123 TParamObject.Destroy + $43 
:000000000041A155 TInterfacedObject._Release + $55 
:000007FEFF2211CE ; C:\Windows\system32\oleaut32.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:\Windows\system32\USER32.dll 
:00000000777D98C2 ; C:\Windows\system32\USER32.dll 
:00000000007A8E84 TApplication.ProcessMessage + $134 
:00000000007A8EF8 TApplication.HandleMessage + $18 
:00000000007A9364 TApplication.Run + $F4 
Impuestos.Impuestos 
:00000000776B59CD ; C:\Windows\system32\kernel32.dll 
:00000000778EA561 ; ntdll.dll 

的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; 

現在表單沒有問題發佈,但這是正確的?,我不會有內存泄漏嗎?

謝謝。

+0

嗨@Marc Guillot。我也許會看看我今晚能否重現這個問題。在我做之前,你的'數據'流是什麼樣的大小?我在問這是否與ServerMethods流返回問題有關。 – MartynA

+0

非常感謝Martyn,這與Datasnap的大流問題無關。即使只有一條記錄(幾十字節),它總是會發生。 –

+0

好吧,我會給它一個旋轉。 CU後來... – MartynA

回答

7

the manual page

設置AsStream屬性設置數據類型屬性ftStream如果不是字符串/字節串/ BLOB數據類型之一。 分配的TStream對象將由此TFDParam擁有。要明確控制所有權,請使用SetStream方法。

強調我的。所以是的,將流分配給參數給出了該流的參數所有權,當它自身被釋放時(它由擁有數據集組件的表單釋放數據集時完成),它負責釋放它。

當你這裏免費流:

Stream := CompressDataset(qryFacturacion_Desglose); 
try 
    spActualizaDesglose.ParamByName('AStream').AsStream := Stream; 
    spActualizaDesglose.ExecProc; 
finally 
    Stream.Free; 
end; 

你正在破壞該參數是抱着爲參考,當參數對象試圖釋放它第二次它提出了一個AV對象。

+0

謝謝@J .... –

+1

@J ...:好看,+1 – MartynA