2010-01-06 8 views
3

Не могли бы вы помочь мне решить эту проблему. Вот мой код. Я храню (в этом примере) 10000 строк, и когда я пытаюсь удалить их, только некоторый объем памяти освобождает остальные утечки.запись и утечка памяти

type 
    PMyData = ^TMyData; 
    TMyData = record 
    Name: string; 
end; 
//////// 

var 
XList:Tlist; 
////////// 

// Here is how I add// 
var 
MyData: PMyData; 
I:Integer; 
begin 
for I:=0 to 10000 do begin 
New(MyData); 
    MyData.Name:='Hello'; 
    XList.Add(TObject(MyData)); 
    end; 
end; 


///Here is how I delete/// 
var 
MyData: PMyData; 
I:Integer; 
begin 
for I:= XList.Count - 1 downto 0 do begin 
MyData:=PMyData (XList[I]); /// I also used (XList.Items[I]) but the result is the same 
    Dispose(MyData); 
    XList.Delete(I); 
end; 

ответ

3

Ваш код выглядит хорошо. Что именно вы имеете в виду, освобождается только какая-то память, а остальные утечки? Получаете ли вы отчеты о утечке памяти из FastMM, или вы просто не видите, что счетчик памяти в диспетчере задач полностью отступил?

Если вы не видите, что ваша программа возвращает всю память, это по дизайну. Он поддерживает некоторые из них, поэтому, если вы выделяете больше памяти, ему не нужно сразу запрашивать больше информации из Windows, что помогает повысить производительность. Память только «просочилась», если диспетчер памяти фактически не отменил ее.

+0

OK. Спасибо за помощь!Я также считаю, что утечки нет, но все же. Это более заметно, когда я добавляю 200000 строк. Например, если я добавляю 200000 строк в первый раз, мое приложение использует (в соответствии с Windows Task Manager: «Mem Usage» - 15304k и «VM Size» - 13492k), я пытаюсь освободить память, и теперь мое приложение использует: 7616k/5800k. Если я добавлю еще две строки (400000), мое приложение теперь использует: 25480k/23436k и 8824k/6768k после того, как я освобожу его, что больше, чем у меня, когда он был освобожден в первый раз (7616k/5800k). Итак, это нормально, чем больше строк я добавляю, тем больше памяти, кажется, течет? – Serhiy

+2

Если вы хотите узнать, действительно ли вы что-то протекаете, поместите 'ReportMemoryLeaksAtShutdown: = true;' в свой DPR и посмотрите, не сообщает ли он что-либо, когда вы выходите из программы. –

6

Я не вижу утечки в этом коде. Как вы определяете, что происходит утечка? Вы смотрите на диспетчер задач? Если это так, то это не является надежным способом обнаружения утечек памяти. Диспетчер памяти VCL не освобождает освобожденную память обратно в ОС, она кэшируется для последующего повторного использования. Диспетчер задач отображает выделенную память. Он не имеет понятия о том, как эта память фактически управляется приложениями.

+2

Лучше сказать, он не освобождает * всю * освобожденную память обратно в ОС. –

4

Диспетчер задач Windows не является надежной мерой использования памяти. Используйте диспетчер памяти FastMM4 с включенной проверкой утечки.

5

Насколько я могу судить, этот код не протекает, если вы эффективно выполняете очищающий код.
Единственный способ узнать, если ваш код утечки, попросив диспетчера памяти сообщать об утечках, добавив эту инструкцию где-то в коде (убедитесь, что он выполняется):

ReportMemoryLeaksOnShutdown := True; 

Менеджер памяти покажет, если любая из памяти, запрашиваемая вашим кодом, не освобождается, когда приложение завершается, т.е. у ВАШЕГО КОДА есть утечка.
После этого задание диспетчера памяти возвращает память ОС после завершения и делает это правильно.

Теперь о том, почему TaskManager сообщает, что больше памяти, по-видимому, не освобождается, когда число строк увеличивается, это связано с тем, что диспетчер памяти не освобождает все ранее запрошенную память до ОС, как только строки освобождаются, если это необходимо снова позже; чтобы избежать повторного запроса из ОС, он сохраняет его.

Как указано в других ответах, TaskManager не является хорошим инструментом, чтобы обнаружить утечки памяти ...

+1

Большое спасибо! Нет утечки. Когда я добавляю строки, а затем очищаю их, диспетчер памяти держится тихо, но когда я добавляю без очистки, он говорит, что есть утечка памяти. Так что все в порядке. Спасибо! – Serhiy

0

Вызов ниже функции перед Dispose или изменить запись в классе (TObject)

Доработка (MyData ^);

Приветствия

+0

Dispose делает Finalize для вас, поэтому вызов Finalize не требуется. –

0

Anytime указатель записи содержит Variant Unbound массив, такие как ... массив ... строки, за исключением типа короткой строки интерфейса вам нужно вызвать финализац, чтобы освободить эти данные, прежде чем делать FreeMem или Dispose. В противном случае используйте класс лучше

Приветствия

0

Try:

FreeAndNil(XList.Items[I]); 
XList.Delete(I); 
+0

Хорошо. Пробовал, но это не сработает. Единственный выход, который я нашел, - использовать XList.Clear, но таким образом весь список очищается, но что, если мне нужно удалить только некоторые элементы. не все из них? XList.Delete (I) не работает, он просто удаляет элемент в TList, но не освобождает память? Хотя XList.Clear удаляет элементы и освобождает память !!! – Serhiy

+0

Нет. Я получаю сообщение об ошибке: Постоянный объект не может быть передан как параметр var. Если я делаю MyData: = PMyData (XList [I]); ///// FreeAndNil (MyData); вместо вашего варианта, он работает, но только один раз. Если я попытаюсь добавить строки еще раз, я получаю Ошибки. – Serhiy

Смежные вопросы