簡體   English   中英

不正確的異常處理/對象釋放可能會導致內存泄漏(原因:未被注意的“變量可能未分配”警告)

[英]Improper exception handling / object freeing probably causes memory leak (Cause: unnoticed “variable might not be assigned” warning)

具有相同問題的示例的完整來源

具有相同問題的示例的完整來源

在單個EXE中繼續所有代碼

我已將所有內容移至單個EXE

var SenderInstance: AutoGeneratedWebserviceUnit.Sender;

...

procedure TForm1.FormCreate(Sender: TObject);
begin
  SenderInstance := AutoGeneratedWebserviceUnit.GetSender(False, 'http://invalid_URL');   // => there is no exception here
end;

...


procedure TForm1.Button1Click(Sender: TObject);
var
  req: AutoGeneratedWebserviceUnit.Request;
  res: AutoGeneratedWebserviceUnit.Response;
begin
  try
    req := Request.Create;
    try
      with req do
      begin
        ID := 0;
        param := 'trash';
      end;
      res := SenderInstance.Request('Login', 'Pass', req);   // => ESOAPHTTPException + EAccesViolation !
      ShowMessage(res.status);
    finally
      req.Free;
      res.Free;   // ### MOST POSSIBLE PROBLEM CAUSE ###
    end;
  except
    on E: Exception do
      ShowMessage(E.Message);
  end;
end;

我了解ESOAPHTTPException, 但是AV? 為什么? ...

問題

引發ESOAPHTTPException之后發生奇怪的事情... 我想是我無法弄清內存泄漏之類的東西,或者我做了一些真正愚蠢的事情...

有設置嗎? 也許我忘記了什么?

線索

我發現了一些關於“ res.Free;”的東西。 try / finally塊內的行禁用此行不會導致任何AV,但是Assigned(req)返回True Assigned(res)也返回True ...

什么...?

導致AV的問題在於Button1Click事件處理程序中的try..finally子句。

您正在試圖釋放你的res變量(響應), 尚未分配的任何東西,因為在調用Request方法失敗並拋出異常。 這意味着它包含垃圾並通過調用res.Free來訪問您不應該訪問的內存位置,這可能會引發幾乎任何奇怪的錯誤。

為了解決它,在進入try..finally之前將res設置為nil ,並在調用res.Free之前檢查是否已分配它。

附帶一提,這是因為res局部變量。 如果它將是類實例的成員 ,則編譯器將自動為其分配一個nil值。

更新

正如@RobKennedy所說的,使用嵌套的 try..finally塊要比我首先告訴您的nil更好(如果某些析構函數失敗,可能會導致問題)。

因此,您將執行以下操作:

req := Request.Create;
try
  req.ID := 0;
  req.param := 'trash';

  res := SenderInstance.Request('Login', 'Pass', req); 
  try
    ShowMessage(res.status);
  finally
    res.Free;
  end;
finally
  req.Free;
end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM