2014-07-15 77 views
0

我有一個程序接受SQL查詢作爲命令行參數,查詢PostgreSQL數據庫並生成一個文件格式爲多種方式之一(通常用於生成CSV文件)。字符串中的Delphi內存泄漏?

但是,該程序有嚴重的內存泄漏 - 一個特定的查詢生成12MB文件,該程序使用8GB的RAM加上幾GB的交換空間,然後操作系統將其殺死。我想找到這個內存泄漏的原因。我不太瞭解德爾菲(根據程序的質量來判斷,原作者也沒有),但我的任務是找到一個快速解決方案。

以下doData函數部分輸出一行結果集。我猜測問題出在「複製」命令的問題上(在堆上創建一個永遠不會釋放的字符串),但我確定有人比我更有經驗能夠確認這個答案,或者指向我正確的方向。

procedure doData; 
var 
    s, fldVal : string; 
    i, fldLen : integer; 
begin 
    s := ''; 

    for i := 0 to ds.Fields.Count-1 do 
    begin 
     if (ds.Fields[i].DataType = ftDate) or 
      (ds.Fields[i].DataType = ftDateTime) then 
     begin 
      if psql.outDate = 'i' then 
       fldLen := 8 
      else 
       fldLen := 10; 

      if ds.Fields[i].IsNull then 
       fldVal := '' 
      else 
       fldVal := formatDate(ds.Fields[i].AsDateTime); 
     end 
     else 
     begin 
      fldLen := ds.Fields[i].DisplayWidth; 
      fldVal := ds.Fields[i].AsString; 
     end; 

     if (psql.outType = 'd') or (psql.outType = 's') then 
      s := s + trim(fldVal) 

     else if psql.outType = 'f' then 
     begin 
      s := s + fldVal; 

      if fldLen - length(fldVal) > 0 then 
       s := s + copy(spaces, 1, fldLen - length(fldVal)); 
       // Is this a memory leak above? 
     end; 

     if psql.outType = 's' then 
     begin 
      if i < ds.Fields.Count-1 then 
      s := s + psql.outDelimChar; 
     end 
     else 
      s := s + psql.outDelimChar; 
    end; 

    writeln(psql.outPrefixData + s); 
end; 
+1

德爾福字符串類型與參考計數管理。當一個字符串變量超出範圍時,它會自動銷燬。 'Copy'不能在這段代碼中產生內存泄漏。 –

+1

如果你生產的是12MB的字符串,那麼你做錯了事情:改用TStringBuilder(或直接寫入流)。但使用's:= s + xx'這樣的代碼對於內存處理來說是非常糟糕的 – Daniel

+0

我發現'MadExcept'是識別內存泄漏的有效工具,但是從你的代碼片段開始,我可能會檢查'ds'和'psql'得到釋放 - 你可能會很幸運...... –

回答

4

此代碼沒有泄漏。 Delphi string類型由編譯器管理,不需要程序員明確的內存釋放。

如果你想找到你的泄漏,你應該包括完整的調試版本FastMM。這將產生診斷報告,包括代碼中任何泄漏的信息,包括幫助識別泄漏內存最初分配位置的堆棧跟蹤。