![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Постоянное разбухание памяти, занимаемой программой [D7, WinXP]
EarlVadim © (2006-04-24 12:22:00)Суть такова.
Раз в минуту программа создает массив из потоков с FreeOnTerminate=true. В самих потоках используются
stfl:=TStringList.Create и FileStream :=TFileStream.Create. В равном им количестве присутствуют stfl.free и FileStream.free.
Результат - каждую минуту увеличение памяти на 50-100кБ.
Но что интересно, если программу свернуть в трей (для чего используется компонента TCoolTrayIcon и развернуть, то размер занимаемой памяти резко уменьшается до уровня первоначального запуска программы.
Подскажите где я мог накосорезить?
Slym (2006-04-27 06:17:00) [1]Кстати кроме памяти (физической), TaskManager умеет показывать другие показатели которые иногда более информативны: виртуальная память, счетчик потоков/дескрипторов/объектов
судя по всему у тебя пухнет счетчик потоков
Сергей М. (2006-04-26 09:51:00) [2]
> вместо 10Мб при старте занимает 250Мб
И все это время программа была "свернута в трей" ?
EarlVadim (2006-04-26 09:29:00) [3]До Out of memory не доходит. Завершаю раньше.
Когда я утром прихожу на работу и вижу что моя программа вместо 10Мб при старте занимает 250Мб, то не надо быть семи пядей во лбу чтобы понять что это ненормально.
Сергей М. (2006-04-26 08:26:00) [4]
> EarlVadim © (25.04.06 14:07) [31]
> память тогда где?
Ты хоть раз получил Out of memory ?
Если утечка действительно имеет место быть, то при наблюдаемой тобой динамике наращивания размера потребляемых ресурсов памяти исключение произойдет довольно скоро ...
EarlVadim (2006-04-25 14:07:00) [5]почему не пользуюсь, под отладчиком все шоколадно.
Перед Suspend все динамические переменные потоков в nil.
А память тогда где?
Сергей М. (2006-04-25 12:53:00) [6]
> EarlVadim © (25.04.06 12:41) [28]
> потому что точно знаю, что жрут память у меня именно потоки.
Это ты обнаружил под отладчиком ?
Или это твои "умозаключения" ?
Ты вообще пользуешься ли отладчиком для решения своих проблем ?
Slym (2006-04-25 12:53:00) [7]EarlVadim © (25.04.06 12:41) [28]
Чушь! и gосле закрытия программы, эта самая программа будет висет в поцессах 60 сек... с опцией "Не отвичает"
Если надо уснуть то Event.WaitFor(60000) и если нужно досрочно разбудить... Event.PulseEvent
EarlVadim (2006-04-25 12:41:00) [8]С Synchronize попробую.
В инете встречал, даже пробовал в варианте со статичной парой поток-элемент. работало. Почему не пошёл дальше даже уже не помню.
Убиванием потока я попытаюсь освобождать память занимаемую им вместе со всеми его переменным, потому что точно знаю, что жрут память у меня именно потоки.
А вот без таймера никак.
Хотя можно в конце цикла ставить не Suspend а Sleep(60000).
evvcom (2006-04-25 11:25:00) [9]
> Все критические моменты программы я довольно чётко понимаю.
Ой ли?
> Основной смысл - потоки должны умирать. а через минуту буду
> создавать новые и так далее.
Неправильно ты понял основной смысл. Более основным смыслом было желание тебе сказать, что поток может сам информировать основной поток о завершении части задачи ему предназначенной (см. Synchronize, Post/SendMessage, другие пока не надо). И совсем не обязательно, что после этого он должен умереть. Может и уснуть. А вот использование таймеров здесь неоправдано. И постоянные циклы (хоть и происходящие с паузами) по проверке состояний ни к чему.
EarlVadim (2006-04-25 11:04:00) [10]Поясню ещё немного.
Поток, отработав засыпает - Suspend.
Но через минуту, по таймеру основного потока получает Resume и отрабатывает полностью с самого начала.
В этот момент в основном потоке таймер Enabled=false.
Когда основной поток увидит, что все дочерние потоки отработали и заснули, он снова запустит таймер на 1 минуту.
Это ответ на вопрос о логике. Что касается эмуляции ошибки, то до них ещё просто не добрался. Все критические моменты программы я довольно чётко понимаю. Но на некоторые я временно "забил".
Что касается длины файлов, то я точно знаю, что это за файлы. И точно знаю в какой момент их можно читать. Так что здесь мин нет.
А вообще я впервые остановился и посмотрел на свой код немного со стороны и вынужден согласится с товарищем, который ничего конкретного не посоветовал, зато прав оказался в главном. Код буду переписывать с нуля.
Основной смысл - потоки должны умирать. а через минуту буду создавать новые и так далее.
Slym (2006-04-25 05:05:00) [11]7. Ты конечно об этом не думал, но твой файл может оказать ся не "твоим", а каким-нибудь "c:\films\porno.avi" 700Мб, а ты его в TStringList! памяти покушает :) лучше смотреть в сторону ReadLn
function ReadLn(Stream:TStream):string;
const cCR = #13; cLF = #10; cEOF = #26;
var Ch:Char;
begin
result:='';
while Stream.Read(Ch,1)>0 do
begin
if Ch=cLF then break;
if Ch=cEOF then break;
if Ch<>cCR then
begin
result:=result+Ch;
continue;
end;
if Stream.Read(Ch,1)=0 then break;
if Ch=cLF then break;
if Ch=cEOF then break;
result:=result+cCR+Ch;
end;
end;
procedure Execute;
var
FileStream:TFileStream;
begin
While FCheck do
try
FileStream:=TFileStream.Create(PChar(CF),fmOpenRead or fmShareDenyRead);
try
FName:=ReadLn(FileStream);
FProg:=StrToIntDef(ReadLn(FileStream),0);
finally
FileStream.Free;
end;
FReady:= true;
except
FReady:= false;
END;
Suspend;
end;
Slym (2006-04-25 04:53:00) [12]EarlVadim © (24.04.06 18:00) [20]
1. STFL.Strings[0]; - Outofbounds :)
2. sniknik © (24.04.06 18:31) [21]
нафига создавать STFL еще не зная понадобится он или нет?
И это верно
3. зачем If FileExists(CF) then begin если всеравно в try оборачиваешь?
4. Вложенные finally сложновато...
5. STFL.Free; не защищен finally...
6. Suspend внутри не есть гуд
sniknik (2006-04-24 21:42:00) [13]> Он сработает один раз, когда программа завершится.
ну и что ты тогда хочеш в процессе работы? жди пока программа завершится... и осводит потоки.
и надейся что нет путаници, что не делаеш Resume какому нибудь потоку раньше чем он отработал и установил Suspend...
кстати зачем цикл? если поток строго только 1 раз отрабатывает. зачем дополнительная переменная выхода из цикла, во первых все одно один раз работает, на Suspend застопорится, во вторых есть стандартная Terminated и метод установки Terminate. и зачем вообще ждать пока отработают все потоки перед завершением? пусть бы себе отрабатывали да закрывались...
не пойму, с логикой чтото запутано/замудрено.
> Так случаев фатальных ошибок с вылетом пока небыло в этом месте.
обработка должна быть на тот случай когда будут... сэмулируй, закрой права на чтение/открой в другом месте эксклюзивно и помосмотри что будет... обработка как раз чтобы этого не было.
EarlVadim (2006-04-24 18:53:00) [14]
> а как же сработает FreeOnTerminate=true
Он сработает один раз, когда программа завершится.
В OnClose передав в потоки
Thread[i].Check:= false;
Thread[i].Resume;
> нафига создавать STFL
Логично, не задумывался. Изменю.
> обработки ошибок нет
Так случаев фатальных ошибок с вылетом пока небыло в этом месте.
Если чтение из файла не состоялось, принимаются значения по умолчанию.
Обе Free отрабатывют, а память растёт.
sniknik (2006-04-24 18:31:00) [15]> Suspend;
????? внутри Execute, а как же сработает FreeOnTerminate=true ?
и несущественное, нафига создавать STFL еще не зная понадобится он или нет?
и посущественнее, обработки ошибок нет.
EarlVadim (2006-04-24 18:00:00) [16]
procedure MyThread.Execute;
begin
While FCheck do BEGIN
STFL:= TStringList.Create;
If FileExists(CF) then begin
try
FileStream := TFileStream.Create(PChar(CF),
fmOpenRead or fmShareDenyRead);
finally
try
STFL.LoadFromStream(FileStream);
finally
FName:= STFL.Strings[0];
FProg:= StrToIntDef(STFL.Strings[1],0);
end;
FileStream.Free;
end;
end;
STFL.Free;
FReady:= true;
Suspend;
FReady:= false;
END;
end;
Сергей М. (2006-04-24 17:08:00) [17]
> знаний предмета не увидел
Ты тут "экзаменатора" не строй из себя. Рано еще, судя по алгоритму.
Хочешь "что-то путное" ?
Выеладывай ключевые моменты алгоритма, скрытые под "..................." в [16].
Про крит.секции, которые ты напрочь игнорируешь, потом поговорим.
EarlVadim (2006-04-24 16:44:00) [18]2Сергей М. ©
Нет желания сказать что-то путное, так и писать не надо.
Кроме общих фраз и "фи" пока знаний предмета не увидел.
Кто-нибудь все-таки по-существу что поправит?
Сергей М. (2006-04-24 16:18:00) [19]
> к вопросу о разбухании памяти какие-то конкретные замечания
> по коду есть?
Нет кода - нет и замечаний.
> Именно там используется
Именно "там" и иллюстрируй в коде.
EarlVadim (2006-04-24 16:16:00) [20]Ну, любой код можно написать минимум 3-мя способами.
Мой, согласен, не займет призовых мест, но он работает.
Вот к вопросу о разбухании памяти какие-то конкретные замечания по коду есть?
Я кстати сильно урезал метод чтения файлов в MyThreadUnit.
Именно там используется
stfl:=TStringList.Create;
FileStream :=TFileStream.Create;
..................
stfl.free;
FileStream.free;