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;
德尔福字符串类型与参考计数管理。当一个字符串变量超出范围时,它会自动销毁。 'Copy'不能在这段代码中产生内存泄漏。 –
如果你生产的是12MB的字符串,那么你做错了事情:改用TStringBuilder(或直接写入流)。但使用's:= s + xx'这样的代码对于内存处理来说是非常糟糕的 – Daniel
我发现'MadExcept'是识别内存泄漏的有效工具,但是从你的代码片段开始,我可能会检查'ds'和'psql'得到释放 - 你可能会很幸运...... –