Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Постоянное разбухание памяти, занимаемой программой [D7, WinXP]


Страницы:   1 2

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;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо