powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
135 сообщений из 135, показаны все 6 страниц
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883175
Я понимаю, что в литературе всё это описано, но иногда не получается найти ответы (обычно знаешь где искать уже когда знаешь ответ). Сильно не бейте за безграмотность в программировании, я любитель.
Я в программе постоянно в огромных количествах работаю с записями состоящими из динамических массивов очень глубокой вложенности и размеров. Так же бывают классы с глубокой вложенностью других классов;
Записи по сути представляют из себя описание конструкции с множеством параметров:
Абстрактный пример, на случай если у вас есть претензии к самой структуре, у меня другая конструкция, но суть такая же
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
ТВелосипед = запись
 Колесо: arrary of ТКолесо;
 Рама: ТРама;
 Руль: ТРуль;
 Дигало:ТДвигало;
 и т.д
Конец;

ТКолесо = запись
 Обод:ТОбод;
 Покрышка:...
 Спица: array of ТСпица;
 ну и т.д.
Конец;

ТСпица = запись
 УчастокСпицы:array of ТУчасток;
Конце;

ТДвигало = запись
 Педали: ТПедали; 
 Цепь: ну и так далее, массивы всякие и прочее
Конец;
Var
 Куча_велосипедов:array of TВелосипед;




С выделением памяти особых проблем нет (если не выделил - сразу словишь ошибку и поправишь), то вот с высвобождением есть вопросы;

1. Если у меня динамические массивы глубокой вложенности, тот воспользовавшись SetLenght(Array,0) никаких потерь памяти не будет? Вопрос возник после прочтения данной темы https://www.programmersforum.ru/showthread.php?t=126357

2. Если у меня динамический массив классов, если после выделения памяти класса уменьшу массив - память станет недоступна (утечка)? Очистка созданных классов обязательна перед уменьшением массива?
Пример
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 TTemp = class
  Data:TData;
 end;
var
 TempArray: array of TTemp;
 i:integer;
Begin
 SetLenght(TempArray,10);
 for i:=0 t0 lenght (TempArray)-1 do 
  TempArray[i].Create;

///...

SetLenght (TempArray,0);
//что происходит с созданными объектами?
end;


3.1. При создании в классе агрегированых классов (ClassB)
Код: pascal
1.
2.
3.
TClassA = class 
   ClassB: TClassB;
End;


При использовании ClassA.Free (или Destroy) будет ли опустошена память которую я выделил под ClassB сама? На данный момент я делаю так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
TClassA = class 
   ClassB: TClassB;
   Destructor  Destroy; override;
End;

destructor TClassA .Destroy;
begin
  if ClassB<>nil then ClassB.Destroy;
  inherited;
end;


Это корректно? Или излишне?


3.2. То же что и 3.1 но если дело будет в потоке, когда поток будет завершен - очиститься ли память от всяких созданных в нем классов, или тоже надо дополнять деструктор?

4. Чуть на другую тему - у меня в Delphi 7 при завершении кода в потоке память не очищается, надо дополнительно использовать Thread.Free; В Делфи 10 такой проблемы нет, после завершения кода память высвобождается. Как в Delphi 7 корректно очистить память после завершения кода потока? (никак не перееду на Delphi 10 ибо раздражают эти мигающие и дергающиеся окошки при компиляции при работе на нескольких мониторах)

5. FreeAndNil применительно к вопросам выше - очистит ли память от агрегированных классов автоматом, если нет - вызовет ли переназначенный деструктор?

6. Если я хочу очистить запись со вложенными динамическими массивами (без классов) до состояния, которое было при её создании, что нужно сделать? Finalize сбросит ли размеры массивов до нулевых? Вроде как через указатели и Get/FreeMem можно, но насколько это корректно? Можно, конечно, создать темповый массив и присваивать его обнуляемому, но как-то костыльно.

7. Ну и вопрос, наверное даже на отдельную тему, но может есть простое решение. Можно ли как нибудь в 32 битной системе решить проблему ограничением на размеры массива.
Один элемент массива в памяти занимает 200-300 мегабайт:
в скомпилированном в Delphi 7 приложении: после 7го увеличения массива вылетает OutOfMemory;
в скомпилированном в Delphi 10 (32 bit) - где-то посл 25го - OutOfMemory;
в скомпилированной в Delphi 10 (64 bit) - открывает сколько угодно (ну сотню точно)
Можно ли как-то решить данную проблему без компиляции в 64битной делфе, так как интерцейс новой делфи мне пока не очень нравится? Кто-то писал про какие-то распределенные массивы (не понял что это). Может через указатели? И без использования БД! :)

Я понимаю, что наиболее логичным мне ответом было бы: - "Иди книжки/Хелп читай". Но в книгах как-то уж очень часто такие вещи опускаются как очевидные, а хелп - это просто уничтожитель времени, зашел, просидел пол дня, ничего не понял :).
Заранее огромное спасибо тем, кто заглянул сюда.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883198
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

Вот здесь есть очень наглядный пример:
https://programmersforum.ru/showthread.php?t=126357
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883204
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

1. Всё почистится, утечек не будет
2. Массив будет освобождён, объекты повиснут в памяти
3.1. Объекты сами не очистятся, нужно удалять в деструкторе. Проверка на NIL лишняя
3.2. Тот же ответ, что и в 3.1.
4. У потока есть свойство FreeOnTerminate
5. FreeAndNil это то же самое, что и Free, но дополнительно обнуляет переменную. Ничего дополнительно очищать не будет (ну в исходники-то можно заглянуть, а?
6. Finalize зачистит поля только управляемых типов (строки, дин. массивы, интерфейсы, варианты), все остальные поля остануться неизменёнными. Если требуется полное обнуление, то после Finalize нужно вызвать FillChar
7. Поддержка 64 бит появилась уже в XE2, не обязательно десятку ставить. Вместо массивов можно навелосипедить абстракцию, которая будет иметь интерфейс массива, а внутри раскладывать элементы по блокам и хранить список блоков (например, массив размером в 1000 элементов, при размере блока в 256 элементов, будет замещён в 4 блоках). Но без дженериков напляшешься пользоваться такими структурами. А если брать версию, где есть дженерики... то уж лучше 64 бита :)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883216
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyПроверка на NIL лишняяЕсли вызывать Free. А у него Destroy
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883217
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Точно, не доглядел.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883222
GerasimenkoАндрей Игоревич,
Вот здесь есть очень наглядный пример:
https://programmersforum.ru/showthread.php?t=126357 Андрей Игоревич1. Если у меня динамические массивы глубокой вложенности, тот воспользовавшись SetLenght(Array,0) никаких потерь памяти не будет? Вопрос возник после прочтения данной темы https://www.programmersforum.ru/showthread.php?t=126357
Ну так этож та же тема, и там пишут - что не освобождается (или я чего не понял). Но
Kazantsev AlexeyАндрей Игоревич,
1. Всё почистится, утечек не будет
Непонятно...
Kazantsev AlexeyПроверка на NIL лишняя
Проверка на nil на случай если я не создал объект (я там их сотнями создаю и уничтожаю в процессе, в конце только часть существует).
А хотя Free и так проверяет на nil..., ну тогда да, хотя что-то у меня с этим было неприятное, с тех пор проверяю.
Kazantsev Alexey У потока есть свойство FreeOnTerminate
Точно, как я о нем забыл... По тестирую.
Kazantsev AlexeyFinalize зачистит поля только управляемых типов (строки, дин. массивы, интерфейсы, варианты), все остальные поля остануться неизменёнными. Если требуется полное обнуление, то после Finalize нужно вызвать FillChar

Тут главный вопрос - сбросит ли сами размеры дин масивов до нуля.
Kazantsev Alexey7. Поддержка 64 бит появилась уже в XE2, не обязательно десятку ставить. Вместо массивов можно навелосипедить абстракцию, которая будет иметь интерфейс массива, а внутри раскладывать элементы по блокам и хранить список блоков (например, массив размером в 1000 элементов, при размере блока в 256 элементов, будет замещён в 4 блоках). Но без дженериков напляшешься пользоваться такими структурами. А если брать версию, где есть дженерики... то уж лучше 64 бита :)
Как-то сложновато и нерационально на первый взгляд. А есть 10я версия делфи сопоставимая по удобности и интерфейсу с 7кой с кучей плагинов (цветные линии, подсветка выделенных переменных, куча всего по мелочи)? И можно сделать, чтоб 10ка при компиляции не сходила с ума масштабируя себя 10 раз (зачем-то перебрасывает окно на основной монитор, затем растягивает, затем ещё что-то делает) и тратя на это в 10 раз больше времени, чем на компиляцию?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883226
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

https://programmersforum.ru/showthread.php?t=126357 Оттуда
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
type
  testArray = array of array of integer;
  TestArray1 = array of integer;
..........
var
  t: TestArray;
  P: Pointer;
begin
  P := nil;
  SetLength(t, 2);
  SetLength(t[0], 2); {первый массив Integer на два элемента}
  SetLength(t[1], 4); {второй массив Integer на 4-ре элемента}

  P:= t[1];

  t[0][0] := 100;
  t[0][1] := -1;

  t[1][0] := 1000;
  t[1][1] := 2000;
  t[1][2] := 3000;
  t[1][3] := 4000;

  if p <> nil then ShowMessage('Ага!');
  SetLength(t, 0);
  ShowMessage(IntToStr(TestArray1(p)[1]));
end;




Проверте на своем массиве
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883233
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичНепонятно...
http://docwiki.embarcadero.com/RADStudio/Rio/en/Dynamic_array#Dynamic_Arrays Dynamic arrays of length 0 have the value nil.
Так понятнее?

Андрей ИгоревичТут главный вопрос - сбросит ли сами размеры дин масивов до нуля.
Я же написал, что зачистит.

Андрей ИгоревичА есть 10я версия делфи сопоставимая по удобности и интерфейсу с 7кой с кучей плагинов (цветные линии, подсветка выделенных переменных, куча всего по мелочи)?
Понятия не имею, я всю эту светомузыку отключаю.

Андрей ИгоревичИ можно сделать, чтоб 10ка при компиляции не сходила с ума масштабируя себя 10 раз (зачем-то перебрасывает окно на основной монитор, затем растягивает, затем ещё что-то делает) и тратя на это в 10 раз больше времени, чем на компиляцию?
Можно поставить не десятку и жить спокойно.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883234
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gerasimenko,

Освобождаемая память очищаться не обязана.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883238
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyGerasimenko,

Освобождаемая память очищаться не обязана.И? Пример то как раз и хорош! Я бы даже сказал, отличный.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883248
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GerasimenkoИ? Пример то как раз и хорош! Я бы даже сказал, отличный.
Если память освободили, но не очистили, она ещё сколько угодно будет сохранять прежние данные, пока они не будут затёрты новыми. А код зашибись, конечно. Читать по протухшему указателю это прям то что нужно.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883252
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyGerasimenkoИ? Пример то как раз и хорош! Я бы даже сказал, отличный.
Если память освободили, но не очистили, она ещё сколько угодно будет сохранять прежние данные, пока они не будут затёрты новыми. А код зашибись, конечно. Читать по протухшему указателю это прям то что нужно.На грабли легко наступить, как выше Вам писали авторЕсли вызывать Free. А у него Destroy
Грабли: они везде расставлены...
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883262
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GerasimenkoНа грабли легко наступить, как выше Вам писали
Ага, только там всё-же Free оказался.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883296
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичТут главный вопрос - сбросит ли сами размеры дин масивов до нуля.

Finalize ничего не делает с размерами массивов, она просто проходится по всем вложенным массивам и записям и освобождает память, занятую под управляемые типы (string, interface и т.п.). Причём только освобождает (т.е. уменьшает счётчики ссылок и делает FreeMem() при необходимости), ЕМНИП она даже не изменяет сами значения полей. SetLength(SomeArray, 0) вызывает Finalize автоматом, если знает что в массиве есть управляемые типы.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883319
Sinemurius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И можно сделать, чтоб 10ка при компиляции не сходила с ума масштабируя себя 10 раз (зачем-то перебрасывает окно на основной монитор, затем растягивает, затем ещё что-то делает) и тратя на это в 10 раз больше времени, чем на компиляцию?
В заголовке Delphi есть выпадающий список desktop-ов.
Когда Вы открыли проект, то у Вас скорее всего установлен desktop "Default Layout".
Затем Вы запускаете проект на отладку, и у Вас меняется desktop на "Debug Layout". По какой то причине, у Вас в этом Desktop-е окно Delphi настроено на расположение в другом мониторе.
Соответственно, в режиме отладки переместите среду Delphi на тот монитор, который Вам нужен, потом нажмите на кнопочку рядом с выпадающим списком desktop-ов и выберите Save desktop.
После этого, расположение окон в desktop-е "Default Layout" сравняется с desktop-ом "Debug Lauout". И после этого, у Вас при запуске проекта на отладку перестанут дергаться окошки.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883443
Kazantsev AlexeyАндрей ИгоревичА есть 10я версия делфи сопоставимая по удобности и интерфейсу с 7кой с кучей плагинов (цветные линии, подсветка выделенных переменных, куча всего по мелочи)?
Понятия не имею, я всю эту светомузыку отключаю.

Помню-помню, настоящие программисты пишут код исключительно в блокноте - остальное от лукавого :).
Просто привык уже этому и сильно ускоряет поиск ошибок.

Kazantsev Alexey http://docwiki.embarcadero.com/RADStudio/Rio/en/Dynamic_array#Dynamic_Arrays Dynamic arrays of length 0 have the value nil.Так понятнее?alekcvpАндрей ИгоревичТут главный вопрос - сбросит ли сами размеры дин масивов до нуля.
Finalize ничего не делает с размерами массивов, она просто проходится по всем вложенным массивам и записям и освобождает память, занятую под управляемые типы (string, interface и т.п.). Причём только освобождает (т.е. уменьшает счётчики ссылок и делает FreeMem() при необходимости), ЕМНИП она даже не изменяет сами значения полей. SetLength(SomeArray, 0) вызывает Finalize автоматом, если знает что в массиве есть управляемые типы.
Понял, спасибо, просто не был уверен, что это делается на всю глубину.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883467
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Короче.
Есть управляемые типы - дин.массивы, строки. Их освобождение - за компилятором. Вручную можно освободить присвоив соответственно nil или '' либо setlength(0).
В записях тоже работает это правило, и все управляемые поля записи также освобождаются автоматом - об этом заботится Finalize.

Есть классы, которые надо создавать и удалять самому.

ТС-у: первой строкой в проекте сделай ReportMemoryLeaksOnShutdown := True; и не гадай на кофейной гуще. А еще лучше - скачай FastMM, подключи его первым модулем в файле проекта и в FastMM4Options.inc в строке {.$define FullDebugModeWhenDLLAvailable} удали точку. Тогда будешь детально видеть, есть ли утечка и что конкретно утекло
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883476
ёёёёё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...продолжается дезинформационная кампания, совмещенная с вирусной рекламой фастмм4.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883491
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ёёёёё...продолжается дезинформационная кампания, совмещенная с вирусной рекламой фастмм4.
"Когда вы говорите, Иван Васильевич, такое впечатление, что вы бредите"
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883803
А как именно FreeOnTerminate завершает поток и очищает память?
Пример:
В делфи7 я могу открыть в потоке 7 массивов за раз.
Если FreeOnTerminate:=false и перед вызовом массива я предварительно FreeAndNil(Thread) - то я могу раз за разом открывать эти 7 массивов;
Если FreeOnTerminate:=true и я ничего не делают перед очередным переотркытием файлов - то 7 я уже отрыть не могу, вылетает ошибка нехватки памяти. Но если открывать по одному (и, вероятно, по 6), то хоть 7, хоть 100 - ничего не вылетает.
Итого получается, что FreeOnTerminate оставляет что-то в памяти, но потом как-то высвобождает (при вызове?)...

Ну и при FreeOnTerminate проверка Thread<>nil - проходит, но при вызове чего бы то ни было (free,Terminate), вылетает ошибка.
Как оно работает?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883811
Michael Longneck
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мда. FreeOnTerminate освобождает память, фактически вызывает MyThread.Free. Никакой связи с тем. что там в потоке делалось тут нет.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883814
Michael Longneck
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"Объект" потока и собственно поток имеют только тут связь, что первое удобно инкапсулирует управление вторым. Но не более того.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39883836
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичА как именно FreeOnTerminate завершает поток и очищает память?
Пример:
В делфи7 я могу открыть в потоке 7 массивов за раз.
Если FreeOnTerminate:=false и перед вызовом массива я предварительно FreeAndNil(Thread) - то я могу раз за разом открывать эти 7 массивов;
Если FreeOnTerminate:=true и я ничего не делают перед очередным переотркытием файлов - то 7 я уже отрыть не могу, вылетает ошибка нехватки памяти. Но если открывать по одному (и, вероятно, по 6), то хоть 7, хоть 100 - ничего не вылетает.
Итого получается, что FreeOnTerminate оставляет что-то в памяти, но потом как-то высвобождает (при вызове?)...

Ну и при FreeOnTerminate проверка Thread<>nil - проходит, но при вызове чего бы то ни было (free,Terminate), вылетает ошибка.
Как оно работает?
FreeOnTerminate := True просто автоматом вызывает TThread.Destroy() после того как завершится выполнение TThread.Execute(). Всё что вы там выделили внутри этого потока - вам же и освобождать в своём деструкторе.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892496
alekcvp
Андрей ИгоревичА как именно FreeOnTerminate завершает поток и очищает память?
Пример:
В делфи7 я могу открыть в потоке 7 массивов за раз.
Если FreeOnTerminate:=false и перед вызовом массива я предварительно FreeAndNil(Thread) - то я могу раз за разом открывать эти 7 массивов;
Если FreeOnTerminate:=true и я ничего не делают перед очередным переотркытием файлов - то 7 я уже отрыть не могу, вылетает ошибка нехватки памяти. Но если открывать по одному (и, вероятно, по 6), то хоть 7, хоть 100 - ничего не вылетает.
Итого получается, что FreeOnTerminate оставляет что-то в памяти, но потом как-то высвобождает (при вызове?)...

Ну и при FreeOnTerminate проверка Thread<>nil - проходит, но при вызове чего бы то ни было (free,Terminate), вылетает ошибка.
Как оно работает?

FreeOnTerminate := True просто автоматом вызывает TThread.Destroy() после того как завершится выполнение TThread.Execute(). Всё что вы там выделили внутри этого потока - вам же и освобождать в своём деструкторе.
Я несколько не о том (или о том).
Примитивный код:
unit1
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
var
  Form1: TForm1;
  MyThread:Thread;
implementation

{$R *.xfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  MyThread:=Thread.Create(True);
  MyThread.FreeOnTerminate:=True;
  MyThread.Resume;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 MyThread.Free;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  MyThread:=Thread.Create(True);
  MyThread.FreeOnTerminate:=false;
  MyThread.Resume;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  if  MyThread<>nil then ShowMessage('Поток не nil') else ShowMessage('Поток nil');
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
   FreeAndNil(MyThread);
end;


unit2
Код: pascal
1.
2.
3.
4.
5.
procedure Thread.Execute;
begin

    ShowMessage('&#207;&#238;&#242;&#238;&#234; &#226;&#251;&#239;&#238;&#235;&#237;&#232;&#235; &#226;&#241;&#229; &#231;&#224;&#228;&#224;&#247;&#232;');
end;





По факту - Thread.Free не делает поток Nil
Thread.FreeOnTerminate:=True; - тоже не делает поток nil.

насколько я понимаю - они только обнуляют все данные, если у меня в потоке создаются огромные массивы - они остаются, занимая память (хотя и обновляются) (в компиляторе их можно прощелкать на всю глубину и посмотреть на нули)
Ну и соответственно проверка на nil тоже не проходит, поток не nil, но вызвать free - уже нельзя, вылетит ошибка памяти
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892498
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичПо факту - Thread.Free не делает поток Nil

Естественно не делает. Не забота объекта следить сколько у тебя указателей на него. Ты их
можешь присвоить хоть миллион, хоть миллиард. Сам наплодил - самому и очищать.

Это азы работы с указателями.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892502
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
если у меня в потоке создаются огромные массивы - они остаются, занимая память
Нет
Андрей Игоревич
в компиляторе их можно прощелкать на всю глубину и посмотреть на нули
Вы видите случайный мусор того, что осталось по старым указателям
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892528
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

чтобы не ловить AV при освобождении несуществующего объекта, попробуй
Код: pascal
1.
2.
3.
4.
procedure TForm1.Button5Click(Sender: TObject);
begin
   if Assigned(MyThread) then FreeAndNil(MyThread);
end;
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892537
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док
Андрей Игоревич,

чтобы не ловить AV при освобождении несуществующего объекта, попробуй
Код: pascal
1.
2.
3.
4.
procedure TForm1.Button5Click(Sender: TObject);
begin
   if Assigned(MyThread) then FreeAndNil(MyThread);
end;


Это и так делается внутри FreeAndNil, не учи человека плохому
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892539
Dimitry Sibiryakov

Андрей ИгоревичПо факту - Thread.Free не делает поток Nil

Естественно не делает. Не забота объекта следить сколько у тебя указателей на него. Ты их
можешь присвоить хоть миллион, хоть миллиард. Сам наплодил - самому и очищать.

Это азы работы с указателями.

Но почему для остальных классов деструктор очищает указатели, а для потоков - нет? И почему тогда штатный Free этого не учитывает (например как предложил Док) и после завершения потока вылетает с ошибкой доступа к памяти.

_Vasilisk_
Андрей Игоревич
если у меня в потоке создаются огромные массивы - они остаются, занимая память
Нет
Андрей Игоревич
в компиляторе их можно прощелкать на всю глубину и посмотреть на нули
Вы видите случайный мусор того, что осталось по старым указателям

Надо потестировать, у других классов ведь полностью очищаются. А если у меня будет миллиард указателей в потоке (ну вдруг я так программирую) - они таки будут сжирать гигабайт памяти?

Док
Андрей Игоревич,

чтобы не ловить AV при освобождении несуществующего объекта, попробуй
Код: pascal
1.
2.
3.
4.
procedure TForm1.Button5Click(Sender: TObject);
begin
   if Assigned(MyThread) then FreeAndNil(MyThread);
end;


Спасибо, очень пригодиться.

А вот есть вопрос из другой оперы (из-за которого я опять вернулся к этому :) )
Вот запускаю я множество потоков, по результатам у меня происходит событие (ну так я сделал) в основном потоке, как сделать так что бы срабатывало только событие последнего выполняемого потока, считать потоки? При том я не знаю сколько у меня потоков и какой именно будет последним. Считать потоки в событии?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892540
Василий 2
Док
Андрей Игоревич,

чтобы не ловить AV при освобождении несуществующего объекта, попробуй
Код: pascal
1.
2.
3.
4.
procedure TForm1.Button5Click(Sender: TObject);
begin
   if Assigned(MyThread) then FreeAndNil(MyThread);
end;


Это и так делается внутри FreeAndNil, не учи человека плохому

Если FreeOnTerminate:=true то FreeAndNil вылетит с ошибкой доступа к памяти.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892552
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Если FreeOnTerminate:=true то FreeAndNil вылетит с ошибкой доступа к памяти.
FreeOnTerminate:=true это совсем другой расклад
довольно низкоуровневый примитив что бы свободно применять его в юзер-коде
для этого нужно очень веское основание
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892560
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Dimitry Sibiryakov

пропущено...

Естественно не делает. Не забота объекта следить сколько у тебя указателей на него. Ты их
можешь присвоить хоть миллион, хоть миллиард. Сам наплодил - самому и очищать.

Это азы работы с указателями.

Но почему для остальных классов деструктор очищает указатели, а для потоков - нет? И почему тогда штатный Free этого не учитывает (например как предложил Док) и после завершения потока вылетает с ошибкой доступа к памяти.

_Vasilisk_
пропущено...
Нет
пропущено...
Вы видите случайный мусор того, что осталось по старым указателям

Надо потестировать, у других классов ведь полностью очищаются. А если у меня будет миллиард указателей в потоке (ну вдруг я так программирую) - они таки будут сжирать гигабайт памяти?
Никто ничего сам, если это не заложено не чистит
Dimitry Sibiryakov и _Vasilisk_ вам правильно написали, надо расти над собой
сам навыделал, сам и чисти, мы же про системный язык, а не про яву рассуждаем???
хотя есть решения и для ленивых 11957089
Андрей Игоревич

Док
Андрей Игоревич,

чтобы не ловить AV при освобождении несуществующего объекта, попробуй
Код: pascal
1.
2.
3.
4.
procedure TForm1.Button5Click(Sender: TObject);
begin
   if Assigned(MyThread) then FreeAndNil(MyThread);
end;


Спасибо, очень пригодиться.

А вот есть вопрос из другой оперы (из-за которого я опять вернулся к этому :) )
Вот запускаю я множество потоков, по результатам у меня происходит событие (ну так я сделал) в основном потоке, как сделать так что бы срабатывало только событие последнего выполняемого потока, считать потоки? При том я не знаю сколько у меня потоков и какой именно будет последним. Считать потоки в событии?
а потом такие советы выдают за советы экспертов :-(
ну вот "посмотреть что делает этот метод" не судьба? или работать надо?

не пользуйтесь FreeOnTerminate:=true и всё будет более-менее в порядке

хотя с тем, что архитектура TThread вызывает много вопросов я очень даже согласен, но что есть то есть
бага записанная в кучу копий, становится фичей
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892564
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
А если у меня будет миллиард указателей в потоке (ну вдруг я так программирую) - они таки будут сжирать гигабайт памяти?
Как вы эти указатели получаете? На каждый New/GetMem/Create должен следовать Dispose/FreeMem/Free. Вызов SetLength() никакой финализации не требует.

При выполнении этих правил никакая память утекать не будет.

Док
чтобы не ловить AV при освобождении несуществующего объекта, попробуй
Код: pascal
1.
2.
3.
4.
procedure TForm1.Button5Click(Sender: TObject);
begin
   if Assigned(MyThread) then FreeAndNil(MyThread);
end;

Док, советуешь феерическую хрень.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892565
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
FreeOnTerminate:=true это совсем другой расклад
довольно низкоуровневый примитив что бы свободно применять его в юзер-коде
для этого нужно очень веское основание
Да ладно. Одно правило нужно выполнять - сохраняем ли мы ссылку на объект или нет
Код: pascal
1.
2.
3.
4.
begin
  FThread := TMyThread1.Create;  // в 95% FreeOnTerminate должно быть False
  TMyThread2.Create;  // в 100% FreeOnTerminate должно быть True
end;
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892566
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичНо почему для остальных классов деструктор очищает указатели

Что-то ты путаешь. Ни для каких классов освобождение памяти не изменяет значение указателя.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892567
kealon(Ruslan)

ну вот "посмотреть что делает этот метод" не судьба? или работать надо?

А как правильно проверять существование потока?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892569
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
А как правильно проверять существование потока?
Потока или экземпляра объекта TThread?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892572
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичА как правильно проверять существование потока?

Правильно - никак. Потоки это оружие класс FaF. Ты его запускаешь, а дальше оно уже само.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892590
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
kealon(Ruslan)

ну вот "посмотреть что делает этот метод" не судьба? или работать надо?

А как правильно проверять существование потока?

1. Если указатель на поток не сохраняется ("TMyThread2.Create;"), то никак.
2. Если указатель на поток сохраняется ("th := TMyThread2.Create;"), то обязательно самому FreeAndNil-ить поток и соответственно "существует" == "th <> nil". FreeOnTerminate - только для п.1
3. Если хочется проверить, завершился ли поток, то есть например ReturnValue, но его все равно надо будет выставить в Execute самому
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892594
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
3. Если хочется проверить, завершился ли поток, то есть например
.Finished, который поток выставляет сам.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892599
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторНо почему для остальных классов деструктор очищает указатели,
Никакой класс не очищает указатель и TThread как представитель классов этого конечно же не делает.
Надежно чистить указатель на TThread можно в OnTerminate потока, вне зависимости от флага FreeOnTerminate.
Другое дело что проверка указателя на nil с включенным флагом FreeOnTerminate мало что гарантирует:
1. Делаем проверку на nil. Поток еще живой
2. Поток надумал закончится, зашел в OnTerminate, обнулил ссылку на себя
3. Обращаемся к потоку получаем AV.
Из плюсов то, что OnTerminate выполняется синхронно с основным потоком. Поэтому могут существовать кейсы когда это будет работать.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892618
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
kealon(Ruslan)
FreeOnTerminate:=true это совсем другой расклад
довольно низкоуровневый примитив что бы свободно применять его в юзер-коде
для этого нужно очень веское основание
Да ладно. Одно правило нужно выполнять - сохраняем ли мы ссылку на объект или нет
Код: pascal
1.
2.
3.
4.
begin
  FThread := TMyThread1.Create;  // в 95% FreeOnTerminate должно быть False
  TMyThread2.Create;  // в 100% FreeOnTerminate должно быть True
end;


makhaon
авторНо почему для остальных классов деструктор очищает указатели,

Никакой класс не очищает указатель и TThread как представитель классов этого конечно же не делает.
Надежно чистить указатель на TThread можно в OnTerminate потока, вне зависимости от флага FreeOnTerminate.
Другое дело что проверка указателя на nil с включенным флагом FreeOnTerminate мало что гарантирует:
1. Делаем проверку на nil. Поток еще живой
2. Поток надумал закончится, зашел в OnTerminate, обнулил ссылку на себя
3. Обращаемся к потоку получаем AV.
Из плюсов то, что OnTerminate выполняется синхронно с основным потоком. Поэтому могут существовать кейсы когда это будет работать.

налопшичить кучу кода, и всё ради "высвободить хэндл как поток завершится", ну и нафига?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892622
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
Док, советуешь феерическую хрень.

че хрень-то сразу? :)

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

kealon(Ruslan)
не пользуйтесь FreeOnTerminate:=true и всё будет более-менее в порядке

им нужно пользоваться, только надо знать где и как :)

Я для себя определил так:
- если экземпляр потока объявлен в локальной переменной, то FreeOnTerminate:=true, ибо после выхода из процедуры видимость переменной все равно потеряется и nil-ить ее специально нет никакой необходимости.
- во всех остальных случаях FreeOnTerminate:= false и FreeAndNil.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892624
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док
че хрень-то сразу? :)

В Лазаре, промежду прочим, если не подставлять эту прокладку, в некоторых случаях получаешь ошибку еще на этапе компиляции. Я сейчас точно ситуацию не воспроизведу кодом (лень, если честно). Но когда я плотно изучал работу потоков, частенько с этим сталкивался.
При чем тут Лазарь-не Лазарь, потоки...
Внутри FreeAndNil и так вызывается проверка на Assigned, как и в Free.
Вот, че.
Уже ж проходили много раз.
А если в указателе (в "переменной объекта") мусор, то эта проверка - абсолютно бесполезна к тому же.


Док
- если экземпляр потока объявлен в локальной переменной, то FreeOnTerminate:=true
Это странный критерий.
Если ждать результатов выполнения потока не нужно, если не нужно управлять потоком - то можно можно использовать FreeOnTerminate, я бы сказал так.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892657
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
Если ждать результатов выполнения потока не нужно, если не нужно управлять потоком - то можно можно использовать FreeOnTerminate, я бы сказал так.
Но таких ситуаций ничтожно мало. Кроме того, при выходе из программы стопорнуть поток как правило всё равно надо, и тут начинаются проблемы.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892660
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
При чем тут Лазарь-не Лазарь, потоки...
Внутри FreeAndNil и так вызывается проверка на Assigned, как и в Free.

В лазаре так (fpc3.0.4: ..\source\rtl\objpas\sysutils\sysutils.inc)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
    procedure FreeAndNil(var obj);
      var
        temp: tobject;
      begin
        temp:=tobject(obj);
        pointer(obj):=nil;
        temp.free;
      end;  


Возможно в дельфях по-другому, давно в потроха не заглядывал

kealon(Ruslan)
при выходе из программы стопорнуть поток как правило всё равно надо

это ты о чем?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892684
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док

В лазаре так (fpc3.0.4: ..\source\rtl\objpas\sysutils\sysutils.inc)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
    procedure FreeAndNil(var obj);
      var
        temp: tobject;
      begin
        temp:=tobject(obj);
        pointer(obj):=nil;
        temp.free;
      end;  


Возможно в дельфях по-другому, давно в потроха не заглядывал

Ты в потроха TObject.Free загляни и узнаешь великую тайну - чем он отличается от .Destroy :)
Док
kealon(Ruslan)
при выходе из программы стопорнуть поток как правило всё равно надо

это ты о чем?

Подозреваю он о том, что при завершении программы нельзя оставлять в памяти работающие потоки.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892685
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

может так проще будет:

автор
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
var
  Form1: TForm1;
  MyThread:Thread;
implementation

{$R *.xfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  MyThread:=Thread.Create(True);
  MyThread.FreeOnTerminate:=True;
  MyThread.OnTerminate:=MyThreadStop;
  MyThread.Resume;
end;

procedure TForm1.MyThreadStop(Sender: TObject);
begin
  MyThread:=nil;
end;




А внутреннюю очистку как-то самостоятельно...
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892701
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
YuRock
Если ждать результатов выполнения потока не нужно, если не нужно управлять потоком - то можно можно использовать FreeOnTerminate, я бы сказал так.
Но таких ситуаций ничтожно мало.
У меня бывали пару раз :)

kealon(Ruslan)
Кроме того, при выходе из программы стопорнуть поток как правило всё равно надо, и тут начинаются проблемы.
Насколько я помню, дельфя такие потоки в массив складывает и при закрытии сама удаляет. Впрочем, проблемы все равно возможны.
Если надо все же вручную закрывать - значит FreeOnTerminate не подходит.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892703
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док
В лазаре так (fpc3.0.4: ..\source\rtl\objpas\sysutils\sysutils.inc)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
    procedure FreeAndNil(var obj);
      var
        temp: tobject;
      begin
        temp:=tobject(obj);
        pointer(obj):=nil;
        temp.free;
      end;  



Возможно в дельфях по-другому, давно в потроха не заглядывал
Это копипаст из делфи. Проверка на нил в Free.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892736
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Василий 2
3. Если хочется проверить, завершился ли поток, то есть например
.Finished, который поток выставляет сам.

Кстати да, спасибо.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892757
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Ты в потроха TObject.Free загляни и узнаешь великую тайну - чем он отличается от .Destroy :)

Ну, таки-да:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
      procedure TObject.Free;
        begin
           // the call via self avoids a warning
           if self<>nil then
             self.destroy;
        end;
              


Тем не менее, без проверки на существование объекта ТС получает AV :)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892822
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док,

AV он получает по совсем другому поводу :)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892830
Kast2K#22022404
Kast2K
Андрей Игоревич,

может так проще будет:

автор
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
var
  Form1: TForm1;
  MyThread:Thread;
implementation

{$R *.xfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  MyThread:=Thread.Create(True);
  MyThread.FreeOnTerminate:=True;
  MyThread.OnTerminate:=MyThreadStop;
  MyThread.Resume;
end;

procedure TForm1.MyThreadStop(Sender: TObject);
begin
  MyThread:=nil;
end;



А внутреннюю очистку как-то самостоятельно...

Выглядит понятно и приятно, попробую так использовать. Очистка это понятно, тут без вопросов.

alekcvp
Василий 2
3. Если хочется проверить, завершился ли поток, то есть например
.Finished, который поток выставляет сам.

Надо изучить и попробовать.


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

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

Примерно так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
.....
//в конце кода потока
Synchronize(DoCurentResultLoad)
....

procedure TOpenResultFiles.DoCurentResultLoad;
begin
 if Assigned(FCurentResultLoad) then FCurentResultLoad(Self);
      //КОД ДЛЯ СОБЫТИЯ
       {var
        LocOpenResultFiles:TOpenResultFiles;
      begin
        if not (Sender is TOpenResultFiles) then Exit;
        LocOpenResultFiles:= Sender as TOpenResultFiles;
        SetLength(Result.Calculation,Length(Result.Calculation)+1);
        Result.Calculation[Length(Result.Calculation)-1]:=LocOpenResultFiles.InTreadResult;
      end;     }
end;




Событием сделал потому, что стараюсь все модули сделать максимально независимыми (желательно полностью) и подключаемыми через библиотеки делфи, так у меня мозг не закипает всех взаимных связей в программе, ну и я могу тестировать модули в отдельных программах.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892880
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
есть куча потоков, которые заканчиваются в разное неизвестное время (открываются и обрабатываются результаты разных расчётов), как по окончании всех потоков вызвать только одно событие,
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
var
  Counter: Integer;

constructor TMyThread.Create;
begin
  inherited Create;
  AtomicIncrement(Counter);
end;

destructor TMyThread.Destroy;
begin
  inherited Destroy;
  if AtomicDecrement(Counter) = 0 then
    DoFinished;
end;
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39892881
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно из потока при завершении дергать основной модуль и ему пихать результаты.
Или можно из основного модуля ждать, пока поток закончит, считывать результаты из поля объекта и удалять его.
Если отправка результатов происходит только единожды за время жизни потока - на мой взгляд, лучше второй вариант.
+ не нужен Synchronize
+ главный модуль все равно следит за состоянием потоков, ему не проблема при завершении забрать данные
+ нет передачи управления, или как там оно правильно называется - не знаток терминологии паттернов и прочих абстракций.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39893081
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
+ не нужен Synchronize

К слову, на лазарусовском форуме тамошние олдфаги настоятельно рекомендуют использовать именно встроенные механизмы общения доп.потока с основным в противовес sendmessages/postmessages. Особенно с учётом кроссплатформенности. И после некоторого своего опыта ия вынужден был согласиться с их доводами
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39893094
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док
К слову, на лазарусовском форуме тамошние олдфаги настоятельно рекомендуют использовать именно встроенные механизмы общения доп.потока с основным в противовес sendmessages/postmessages. Особенно с учётом кроссплатформенности. И после некоторого своего опыта ия вынужден был согласиться с их доводами

Олдфаги такие... олдфаги. Они ж сделали мультиплатформенную очередь сообщений, почему бы его не применять. Да и банальный ThreadQueue никто не отменял

На Praxis, кстати, тамошние олдфаги имеют прямо противоположное мнение насчет синхронайза
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39893096
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док
Особенно с учётом кроссплатформенности
Ну дык какие sendmessages/postmessages на кроссплатформе? Там вообще про модуль Windows нужно забыть
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39893140
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
kealon(Ruslan)
пропущено...
Но таких ситуаций ничтожно мало.
У меня бывали пару раз :)

kealon(Ruslan)
Кроме того, при выходе из программы стопорнуть поток как правило всё равно надо, и тут начинаются проблемы.
Насколько я помню, дельфя такие потоки в массив складывает и при закрытии сама удаляет. Впрочем, проблемы все равно возможны.
Если надо все же вручную закрывать - значит FreeOnTerminate не подходит.

Да, там есть такая фигня, но вот незадача, если есть куча используемых в этом потоке юнитов и они финализируются, могут начаться "чудеса". Особенно это актуально при сопровождении такого кода, когда идёт кусочная добавка и вполне работающий код может превратиться в тыкву.
У меня тоже бывало, что иначе ещё хуже выходит, но если при баге вижу что это вбито просто так, я лучше перепишу от греха подальше.

Делал как-то трюк с record + interface для финализации что бы не использовать напрямую такое недоразумение как TThread. Вполне живо было, но выходило слишком громоздко.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39893147
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич, _Vasilisk_,

еще лучше разобраться с WaitForMultipleObjects:
https://stackoverflow.com/questions/6867105/waiting-for-multiples-threads-using-waitformultipleobjects
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39893158
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaon
еще лучше разобраться с WaitForMultipleObjects:
А, что там разбираться? И главное зачем? Завесить программу, пока остальные потоки работают? Я думаю, что это не то, чего хотел TC. Можно прикрутить MsgWaitForMultipleObjects и реализовать локальный оконный цикл, но опять таки зачем?

Дальше, там ограничение в 64 хэндла, а ТС хочет потоки запускать и останавливать. Ну и никакого FreeOnTerminate (или предварительный вызов DuplicateHandle())

В общем для этой задачи атомарный инкремент/декремент гораздо правильное решение
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39893234
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
Там вообще про модуль Windows нужно забыть

Не совсем так. Методы описаны в LCLInfl и LCLType, формально работают на кроссплатформе, но... я уже писал про это выше ;)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894583
Всё указанные способы попробовал, всё работает, огромное спасибо.

Теперь следующий вопрос в познании программирования :). А надо ли очищать память при выходе из программы, у меня в главном потоке в процессе работы создается (и используется) огромное число разнообразных классов - нужно ли их высвобождать при закрытии, или система всё зачистит и так?

Вопрос совсем не в тему, но мелоковат на отдельную тему.
Есть программы, которые периодически скидывают данные в текстовые файлы, есть одна программа, которая периодически эти данные считывает.
Записываются файлы классическим WriteLn, считываются TSringList.LoadFromFile();
Но! Иногда при считывании вылетала ошибка о том, что файл открыт на запись (что логично), на данный момент обыграл функцией проверяющей доступность файла, вроде не вылетает ошибка, но может просто везет.
функция проверки доступности FileIsUse
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function FileIsUse(fName: string): boolean;   //проверка файла на открытия не запись
  var
    HFileRes: HFILE;
  begin
    Result := false;
    if not FileExists(fName) then exit;
    HFileRes := CreateFile(pchar(fName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    Result := (HFileRes = INVALID_HANDLE_VALUE);
    if not Result then CloseHandle(HFileRes);
  end;



В коде делают так
Код: pascal
1.
2.
     while FileIsUse (FilePath) do Sleep(10);
     ListFile.LoadFromFile(FilePath);


Но как-то сомнения, что так правильно.

Ну и обратный вопрос LoadFromFile() не блокирует файл для записи? (что гораздо страшнее, так записывающую программу ломать очень не хочется)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894614
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
нужно ли их высвобождать при закрытии
Нужно.
Андрей Игоревич
или система всё зачистит и так?
Система освободит занимаемую память и некоторые ресурсы, но деструкторы не вызовутся. Например, атомы глобальны и системой не освобождаются
Андрей Игоревич
Вопрос совсем не в тему,
Так создайте отдельный вопрос
Андрей Игоревич
Код: pascal
1.
 while FileIsUse (FilePath) do Sleep(10);

это полные бред
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894675
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич

В коде делают так
Код: pascal
1.
2.
     while FileIsUse (FilePath) do Sleep(10);
     ListFile.LoadFromFile(FilePath);



можно сделать так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
  if FileExist(FilePath)
  repeat
    try
     ListFile.LoadFromFile(FilePath);
    except // тут еще по-хорошему надо ловить именно ошибки совместного доступа, плюс счетчик, чтобы не зациклилось
      Sleep(10);
    end;
  until False;



LoadFromFile блокирует, если надо, чтобы не блокировал - TFileStream и FileMode
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894699
Василий 2
Андрей Игоревич

В коде делают так
Код: pascal
1.
2.
     while FileIsUse (FilePath) do Sleep(10);
     ListFile.LoadFromFile(FilePath);



можно сделать так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
  if FileExist(FilePath)
  repeat
    try
     ListFile.LoadFromFile(FilePath);
    except // тут еще по-хорошему надо ловить именно ошибки совместного доступа, плюс счетчик, чтобы не зациклилось
      Sleep(10);
    end;
  until False;



LoadFromFile блокирует, если надо, чтобы не блокировал - TFileStream и FileMode

Обработку исключений в принципе уже видел на всех форумах, но не слишком ли это? И нет никаких проблем при обработке исключений в потоке? TFileStream и FileMode подумаю, просто где-то на форумах видел утверждение, что LoadFromFile не блокирует, но утверждение уровне комментария на ответы.майл.ру :). Надо подумать...
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894700
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичИ нет никаких проблем при обработке исключений в потоке?

Проблемы неизбежны если НЕ обрабатывать исключения в потоке.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894714
Dimitry Sibiryakov

Андрей ИгоревичИ нет никаких проблем при обработке исключений в потоке?

Проблемы неизбежны если НЕ обрабатывать исключения в потоке.

Сам код естественно заключен в try except, но именно как защита от ошибок, просто всегда понимал исключения именно как что-то к чему прибегают в "исключительных" случаях, а не как часть функционала процедуры.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894726
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Сам код естественно заключен в try except, но именно как защита от ошибок, просто всегда понимал исключения именно как что-то к чему прибегают в "исключительных" случаях, а не как часть функционала процедуры.

1. Главное чтобы в блоке except не было ничего, что может хотя бы в теории вернуть необработанное исключение.
2. try ... finally / except не рекомендуется использовать в циклах, т.к. это не самый быстрый код (во всяком случае в x86), но вне их они не критичны. Есть даже такая команда Abort , которая вызывает "тихое" исключение (стандартный обработчик его не отображает), которая используется для быстрого выхода из процедур большого уровня вложенности.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894778
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
Андрей Игоревич

В коде делают так
Код: pascal
1.
2.
     while FileIsUse (FilePath) do Sleep(10);
     ListFile.LoadFromFile(FilePath);



можно сделать так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
  if FileExist(FilePath)
  repeat
    try
     ListFile.LoadFromFile(FilePath);
    except // тут еще по-хорошему надо ловить именно ошибки совместного доступа, плюс счетчик, чтобы не зациклилось
      Sleep(10);
    end;
  until False;



LoadFromFile блокирует, если надо, чтобы не блокировал - TFileStream и FileMode

alekcvp
Андрей Игоревич
Сам код естественно заключен в try except, но именно как защита от ошибок, просто всегда понимал исключения именно как что-то к чему прибегают в "исключительных" случаях, а не как часть функционала процедуры.

1. Главное чтобы в блоке except не было ничего, что может хотя бы в теории вернуть необработанное исключение.
2. try ... finally / except не рекомендуется использовать в циклах, т.к. это не самый быстрый код (во всяком случае в x86), но вне их они не критичны. Есть даже такая команда Abort , которая вызывает "тихое" исключение (стандартный обработчик его не отображает), которая используется для быстрого выхода из процедур большого уровня вложенности.
меня всегда удивляет, где вы всё это находите
а ещё больше удивляет как компонуете в общем-то правильную инфу в странные выводы.

за глухой except по рукам бить надо, а при повторении ситуации возможно и интерфейсом об тейбл
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894888
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
меня всегда удивляет, где вы всё это находите
а ещё больше удивляет как компонуете в общем-то правильную инфу в странные выводы.

А меня всегда удивляет, что люди начинают отвечать не попытавшись понять прочитанное. Я отвечал не на отрывок с кодом выше, а про обработку исключений в потоках. Где там про глухой except было?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39894896
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
меня всегда удивляет, где вы всё это находите
а ещё больше удивляет как компонуете в общем-то правильную инфу в странные выводы.

за глухой except по рукам бить надо, а при повторении ситуации возможно и интерфейсом об тейбл

Вот только не надо ортодоксальности. Всё зависит от цели. Если цель - открыть файл, то совершенно без разницы, по какой там причине вспухло исключение. К тому же есть дополнение насчет ловли и счетчика.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895003
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

по вашему посту подчёркнуто "Главное" - Не Главное, эксепшены группируются в список, это вполне нормальная ситуация для анализа ошибки - тынц

Василий 2
kealon(Ruslan)
меня всегда удивляет, где вы всё это находите
а ещё больше удивляет как компонуете в общем-то правильную инфу в странные выводы.

за глухой except по рукам бить надо, а при повторении ситуации возможно и интерфейсом об тейбл

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

PS: если подцепить обработчик крашей вроде EurekaLog или Madshi, то сопровождение приложения заметно улучшится
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895027
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
try ... finally/except не рекомендуется использовать в циклах, т.к. это не самый быстрый код (во всяком случае в x86)
ЕМНИП, тормоза будут только в случае исключительных ситуаций.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895052
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)

Тут больше дело в проблемах возникающих в таком коде при сопровождении, человек примет это как данность, а не угрозу - размножит этот подход (а чёп нет, просто же?), код даже из этого примера легко разрастётся, могут проявиться другие исключения. Из-за такого вот упрощения поиск ошибки в коде может занять очень длительное время.
Всегда лучше чётко описать конкретные исключения, отправив неизвестное гулять дальше - это не такая большая проблема.

PS: если подцепить обработчик крашей вроде EurekaLog или Madshi, то сопровождение приложения заметно улучшится

Это всё верно, но в данном случае - из пушки по воробьям. Вроде того Hello world MVC с листингом на три экрана. Но согласен, что такие допущения должны вноситься осознанно.

Barmaley57
kealon(Ruslan)
try ... finally/except не рекомендуется использовать в циклах, т.к. это не самый быстрый код (во всяком случае в x86)
ЕМНИП, тормоза будут только в случае исключительных ситуаций.

Нет, замерил специально, try секции замедляют почти в три раза.
Ops/sec: 1716247 / 612494. Правда, значимой задержка начинает быть при кол-ве итераций от 150 млн.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895054
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
del, дубль
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895182
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
Barmaley57
пропущено...
ЕМНИП, тормоза будут только в случае исключительных ситуаций.

Нет, замерил специально, try секции замедляют почти в три раза.
Ops/sec: 1716247 / 612494. Правда, значимой задержка начинает быть при кол-ве итераций от 150 млн.


В x86 обработка исключений никак не регулируется стандартом. для try-секции компилятор создаёт допкод, который записывает в стек инфу для восстановления - естественно это будет замедлять основной код

В x64 допкод не создаётся, компилятор только добавляется раскрутку в блок данных программы, соответственно и try-блок не добавляет кода и не замедляет выполнение. Но это сильно затрудняет анализ, отсюда и обработка исключения в случае его появления будет медленее, чем на x86.

Например, в питоне, особенно активно используются исключения для различных ветвлений, это давало довольно сильные тормоза для x64-билда.

PS: всё вышесказанное относится к компиляции под винду
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895188
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
alekcvp,
по вашему посту подчёркнуто "Главное" - Не Главное, эксепшены группируются в список, это вполне нормальная ситуация для анализа ошибки - тынц

Ага, цитата по вашей же ссылке:по-умолчанию, вложенные исключения не запоминаются. Чтобы сохранить вложенное исключение, вам нужно возбудить его через Exception.RaiseOuterException (стиль Delphi) или Exception.ThrowOuterException (стиль C++ Builder). Это как с трассировкой стека: они сделали возможность , но если вам это надо, то реализацию пишите сами, ручками. Т.е. очевидно что по-умолчанию там ничего хорошего не получится. И кроме того, мы говорили о потоках , а в потоках за пределы Execute() никакие исключения выходить не должны, да?..
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895198
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Это как с трассировкой стека: они сделали возможность , но если вам это надо, то реализацию пишите сами, ручками. Т.е. очевидно что по-умолчанию там ничего хорошего не получится. И кроме того, мы говорили о потоках , а в потоках за пределы Execute() никакие исключения выходить не должны, да?..
зачем тогда для потока делать объект-исключение?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895200
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
в потоках за пределы Execute() никакие исключения выходить не должны, да?..
Не обязательно
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
function ThreadProc(Thread: TThread): Integer;
var
  FreeThread: Boolean;
begin
  TThread.FCurrentThread := Thread;
{$IF Defined(MACOS)}
  if Thread.FSuspended then
    pthread_mutex_lock(Thread.FCreateSuspendedMutex);
{$ELSEIF Defined(LINUX)}
  if Thread.FSuspended then
    sem_wait(Thread.FCreateSuspendedSem);
{$ENDIF LINUX}
  try
    if not Thread.Terminated then
    try
      Thread.Execute;
    except
      Thread.FFatalException := AcquireExceptionObject;
    end;
  finally
    Result := Thread.FReturnValue;
    FreeThread := Thread.FFreeOnTerminate;
    Thread.DoTerminate;
    Thread.FFinished := True;
    SignalSyncEvent;
    if FreeThread then Thread.Free;
{$IF Defined(MSWINDOWS)}
    EndThread(Result);
{$ELSEIF Defined(POSIX)}
    // Directly call pthread_exit since EndThread will detach the thread causing
    // the pthread_join in TThread.WaitFor to fail.  Also, make sure the EndThreadProc
    // is called just like EndThread would do. EndThreadProc should not return
    // and call pthread_exit itself.
    if Assigned(EndThreadProc) then
      EndThreadProc(Result);
    pthread_exit(Result);
{$ENDIF POSIX}
  end;
end;

...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895227
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
alekcvp
в потоках за пределы Execute() никакие исключения выходить не должны, да?..
Не обязательно
Это всё красиво в коде, но когда доходит до дела, то в рандомных местах случается AV. Особенно если исключение "выпустить" где-нибудь в OnThreadFinished. Пытался разобраться, но дошёл до того что он это исключение пытается перенести через Synchronize из вторичного потока в главный и где-то что-то у него идёт не так как задумано. В итоге пришёл к тому, что если не хочешь проблем - исключения не должны покидать методы и события потока.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895235
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,
да, у них там косяк
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
function ThreadProc(Thread: TThread): Integer;
var
  FreeThread: Boolean;
begin
  TThread.FCurrentThread := Thread;
{$IF Defined(MACOS)}
  if Thread.FSuspended then
    pthread_mutex_lock(Thread.FCreateSuspendedMutex);
{$ELSEIF Defined(LINUX)}
  if Thread.FSuspended then
    sem_wait(Thread.FCreateSuspendedSem);
{$ENDIF LINUX}
  try
    if not Thread.Terminated then
    try
      Thread.Execute;
    except
      Thread.FFatalException := AcquireExceptionObject;
    end;
  finally
    Result := Thread.FReturnValue;
    FreeThread := Thread.FFreeOnTerminate;
    Thread.DoTerminate;
    Thread.FFinished := True;
    SignalSyncEvent;
    if FreeThread then Thread.Free;
{$IF Defined(MSWINDOWS)}
    EndThread(Result);
{$ELSEIF Defined(POSIX)}
    // Directly call pthread_exit since EndThread will detach the thread causing
    // the pthread_join in TThread.WaitFor to fail.  Also, make sure the EndThreadProc
    // is called just like EndThread would do. EndThreadProc should not return
    // and call pthread_exit itself.
    if Assigned(EndThreadProc) then
      EndThreadProc(Result);
    pthread_exit(Result);
{$ENDIF POSIX}
  end;
end;

и в этом обработчике исключение нельзя выпускать
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895272
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
alekcvp,
да, у них там косяк
и в этом обработчике исключение нельзя выпускать

Сегодня нельзя в этом, завтра нельзя в другом, мораль: не хочешь проблем - не выпускай ни в каком :)
Там в самом DoTerminate, вроде, ещё какая-то обработка исключений есть. Исходников просто сейчас нет под рукой.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895390
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

нету там ничего для защиты
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
procedure TThread.DoTerminate;
begin
  if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
end;
...
procedure TThread.CallOnTerminate;
begin
  if Assigned(FOnTerminate) then FOnTerminate(Self);
end;
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895579
Cobalt747
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич

Thread.FreeOnTerminate:=True; - тоже не делает поток nil.

FreeOnTerminate имеет смысл использовать только если ты создал поток и отпустил его в свободное плавание.
или в деструкторе потока сам озаботился очистить за собой единственную ссылку где-нить в списке потоков.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895630
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
Нет, замерил специально, try секции замедляют почти в три раза.
Да быть такого не может! Какая же там "нагрузка" в цикле?)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895883
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57
Василий 2
Нет, замерил специально, try секции замедляют почти в три раза.
Да быть такого не может! Какая же там "нагрузка" в цикле?)

foo:=i :D
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895890
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2

foo:=i :D
А если без отладчика и в release запустить?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895912
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat
Василий 2

foo:=i :D
А если без отладчика и в release запустить?

То же самое.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895944
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
rgreat
пропущено...
А если без отладчика и в release запустить?

То же самое.
Значит там есть и except блок и finally. Только с except потеря - максимум 20%
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39895955
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57
Василий 2
пропущено...

То же самое.
Значит там есть и except блок и finally. Только с except потеря - максимум 20%
Если есть finally - значит есть и except, как минимум неявный.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896116
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
Barmaley57
пропущено...
Значит там есть и except блок и finally. Только с except потеря - максимум 20%
Если есть finally - значит есть и except, как минимум неявный.

Вот странно: есть там есть неявный except, то почему не сделать конструкцию вида: try .. except ... finally ... end ?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896137
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp> почему не сделать конструкцию вида: try .. except ... finally ... end ?

Насколько я помню, еще лет 15 назад был соотв. тикет.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896358
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Вот странно: есть там есть неявный except, то почему не сделать конструкцию вида: try .. except ... finally ... end ?
Экономия небольшая - всего лишь лишние try и end.

К тому же, в таком случае не совсем очевидно, что будет выполнено первым - except или finally.
Тем более, что я бы, например, хотел бы, чтобы можно было регулировать последовательность:
и так
try ... except ... finally ... end
и так
try ... finally ... except ... end
Но это приведет к ухудшению наглядности кода.

Т.ч. лучше (для наглядности) вручную писать два блока, каких хочешь. Так код понятнее.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896419
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
К тому же, в таком случае не совсем очевидно, что будет выполнено первым - except или finally.

Мне трудно судить, как там это видно с позиций новичка, но вроде вполне очевидно, что finally должен выполняться в финале, сиречь последним
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896421
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
alekcvp
Вот странно: есть там есть неявный except, то почему не сделать конструкцию вида: try .. except ... finally ... end ?
Экономия небольшая - всего лишь лишние try и end.

К тому же, в таком случае не совсем очевидно, что будет выполнено первым - except или finally.
Тем более, что я бы, например, хотел бы, чтобы можно было регулировать последовательность:
и так
try ... except ... finally ... end
и так
try ... finally ... except ... end
Но это приведет к ухудшению наглядности кода.

Т.ч. лучше (для наглядности) вручную писать два блока, каких хочешь. Так код понятнее.

Очень наглядно:
Код: pascal
1.
2.
3.
4.
5.
6.
try
  try
  except
  end
finally
end


По сравнению с:
Код: pascal
1.
2.
3.
4.
try
except
finally
end


Последовательность очевидна: try ... except ... finally ... end , т.к. finally из самого названия следует выполняться последней.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896440
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Последовательность очевидна: try ... except ... finally ... end , т.к. finally из самого названия следует выполняться последней.

Ну хорошо, согласен.
Еще один момент.
Если в except произойдет еще одно исключение - я так понимаю, что finally всё равно должно выполниться, так все захотят 100%.
Получается, для finally компилятору нужно будет сделать еще один неявный блок try ... except . В общем, все не так просто и очевидно, как кажется.

В любом случае, мне - более наглядно так:
Код: pascal
1.
2.
3.
4.
5.
6.
try
  try
  except
  end
finally
end


или так:
Код: pascal
1.
2.
3.
4.
5.
6.
try
  try
  finally
  end
except
end



В зависимости от необходимости и ситуации.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896446
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
YuRock
пропущено...
Если есть finally - значит есть и except, как минимум неявный.

Вот странно: есть там есть неявный except, то почему не сделать конструкцию вида: try .. except ... finally ... end ?

https://quality.embarcadero.com/browse/RSP-18291

Resolution: Won't Fix


Marco Cantù with comment:
We are keeping exception blocks as they have been. Works good enough.

Ленивые гандоны.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896480
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat
Ленивые гандоны.
Ты хочешь, чтобы они еще бы и исключения поломали? Ты представляешь сколько их потом будут чинить?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896483
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Ты это к тому что они не только ленивые но и криворукие? ;)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39896490
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat,

Они криворукие и потому ленивые осторожные
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902422
Мозг кипит и плавиться из-за безграмотности.
Мне вот тут выше посоветовали вызывать финальную процедуру только тогда, когда счетчик потоков дойдет до нужного (и тут я косякнул и наловил проблем с тем, что счетчик мог понизиться сразу у всех потоков и все потоки бы вызвали процедуры, но это я победил, наверно).

Но суть текущего вопроса вот в чем, по окончании работы Потока я всегда вызываю событие в главном потоке, передаю считанные данные главному потоку. Если потоков много и они почти одновременно вызывают события, то при каком-то стечении обстоятельств (видимо когда накапливается слишком много ожидающих) - вылетает "конец памяти".
Хорошо тестируется в чистой программе, где вызвать 100 потоков и назначить событие Onterminate с какими-нибудь действиями.

Помимо этого для отлова ошибок я во все ключевые процедуры вначале вставил процедуру в которой отправляю сообщение в "ЛОГ" (вызывая тоже некоторое число процедур для ведения ЛистВиева и сохранения в файл)
Код: pascal
1.
 PostMessage (DebugForm.Handle,ERROR_DATA_MESSAGE,DWORD(PChar(Er_Message)),DWORD(PChar(Discription)));


И, судя по всему, в моменты каллапса с событиями эти сообщения этот каллапс ещё больше увеличивают и всё быстрее падаетс "Концом памяти".
Товарищи пряморукие - подскажите, как можно решить таки проблемы?.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902427
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
13.12.2019 11:40, Андрей Игоревич пишет:
>
> Мозг кипит и плавиться из-за безграмотности.

Курсы русского языка для взрослых
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902474
Мимопроходящий

13.12.2019 11:40, Андрей Игоревич пишет:
>
> Мозг кипит и плавиться из-за безграмотности.

Курсы русского языка для взрослых

Как всегда спасибо за дельный и своевременный совет, вы как всегда крайне желанны в любой моей теме.
П.С. За ошибку стыдно, как раз отвлекли и писал максимально быстро сообщение, зря.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902475
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич, вы сможете подготовить приложение (для тестов, с одной кнопкой), в котором бы воспроизводилась проблема и выложить исходники здесь?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902476
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
13.12.2019 12:54, DmSer пишет:
> выложить исходники здесь?

гы-гы
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902494
Zelius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

Если не хватает памяти, можно попробовать x64, ее сразу станет больше.
Либо не заниматься перевыделением памяти, выделять один раз и потом использовать, передавать только ссылки на нее.

P.S. PostMessage (DebugForm.Handle,ERROR_DATA_MESSAGE,DWORD(PChar(Er_Message)),DWORD(PChar(Discription))); - плохая идея, если Er_Message и Discription не статичны, возможен вариант, что сообщение ушло, память под строки освободилась, и только тут сообщение начинает обработку.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902537
DmSer
Андрей Игоревич, вы сможете подготовить приложение (для тестов, с одной кнопкой), в котором бы воспроизводилась проблема и выложить исходники здесь?

Точно причину не пойму, сейчас в отдельном приложении, вроде, работает, но не хватает времени потестить почему работает, не работало же :), но суть проблемы, что в таком коде периодически вылетает "Конец памяти".

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
procedure TForm1.Button1Click(Sender: TObject);
var
  i:integer;
begin
  for i:=1 to 1000 do
   begin
    MyTread:=TMYTread.Create(True);
    MYTread.FreeOnTerminate:=true;
    MyTread.OnMyEvent:=MyEvent;
    MyTread.Resume;
   end;
end;

procedure TForm1.MyTerminate(Sender: TObject);
Begin
Memo1.Lines.Add('END');

Unit2...

....
    property  OnMyEvent  :   TNotifyEvent read FMyEvent    write FMyEvent;
....

procedure TMYTread.Execute;
begin
  DoMyEvent;
end;

procedure TMYTread.DoMyEvent;
begin
 if Assigned(FMyEvent) then FMyEvent(Self);
end;

end;



А, стоп, яж в событии делаю так

Код: pascal
1.
2.
3.
4.
5.
var
  LocOpenResultFiles:TOpenResultFiles;
begin 
     if not (Sender is TOpenResultFiles) then Exit;
    LocOpenResultFiles:= Sender as TOpenResultFiles;



А LocOpenResultFiles у меня 300-500 метров.... Тогда может и в этом делало, а не событиях :)

Zelius
Андрей Игоревич,

Если не хватает памяти, можно попробовать x64, ее сразу станет больше.
Либо не заниматься перевыделением памяти, выделять один раз и потом использовать, передавать только ссылки на нее.

P.S. PostMessage (DebugForm.Handle,ERROR_DATA_MESSAGE,DWORD(PChar(Er_Message)),DWORD(PChar(Discription))); - плохая идея, если Er_Message и Discription не статичны, возможен вариант, что сообщение ушло, память под строки освободилась, и только тут сообщение начинает обработку.


64 использую уже повсеместно (хотя хз, вылетает ли там это сообщение, я там только финально компилирую). А вот про сообщение большое спасибо, то-то у меня периодически какая-то ересь приходило. Как более корректно передавать такие данные?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902561
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Как более корректно передавать такие данные?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
p: PString;
New(p);
p^:=s;
PostMessage(...p)

...
p := PString(Msg.lParam);
...
Dispose(p)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902640
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Мне вот тут выше посоветовали вызывать финальную процедуру только тогда, когда счетчик потоков дойдет до нужного (и тут я косякнул и наловил проблем с тем, что счетчик мог понизиться сразу у всех потоков и все потоки бы вызвали процедуры, но это я победил, наверно)
Вы же вот так 22022741 делали? Правда?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902829
Zelius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
Андрей Игоревич
Как более корректно передавать такие данные?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
p: PString;
New(p);
p^:=s;
PostMessage(...p)

...
p := PString(Msg.lParam);
...
Dispose(p)


можно так, а если главный поток ничем не занят, то можно не заморачиваться и сделать SendMessage
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39902954
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zelius
можно не заморачиваться и сделать SendMessage

а еще можно вызвать потокобезопасные Synchronize/Queue. Немного не изящно, но надежно :)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906018
Наконец, появилась миллисекунда свободного времени.
Zelius

можно так, а если главный поток ничем не занят, то можно не заморачиваться и сделать SendMessage

Очень часто бывает так, что прям ну очень занят, потому не хотелось бы.
Кстати, а можно ли как-то форму целиком запихнуть в отдельный поток, или это слишком сложно, и ну его нафиг?

Василий 2
Андрей Игоревич
Как более корректно передавать такие данные?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
p: PString;
New(p);
p^:=s;
PostMessage(...p)

...
p := PString(Msg.lParam);
...
Dispose(p)



Пока не очень дружил с указателями. Правильно же?
такая передача сообщений корректна, real - как пример передачи других данных
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
procedure TForm1.SendMessage;
var
  TestStr  :string;
  TestReal :Real;
  pStr:   ^string;
  pReal:  ^Real;
begin
  TestStr:=  'Message';
  TestReal:=12345.6789;
  New(pStr);  
  New(pReal);
  pStr^:=TestStr;   pReal^:=TestReal;
  PostMessage (Form1.Handle,MY_MESSAGE1,Integer(pStr),Integer(pReal));
end;

procedure TForm1.INMessage (var msg: TMessage);
var
 psrt:^string;
 pRl:^real;
begin
 New(psrt);
 psrt:=Pointer(msg.WParam);
 pRl:=Pointer(msg.LParam);
 memo3.Lines.Add((psrt^)+' '+floattostr(pRl^));
 Dispose(psrt); Dispose(pRl);
end;


Но возникает вопрос два вопроса, первый может ли очередь формируемая PostMessage переполниться (например принимающий поток сильно занят) и к чему это приведет? Если сообщение "не доходит" по тем или иным причинам - не будет ли утечки памяти, так как код "Dispose" у нас только в принимающем обработчике.

_Vasilisk_
Андрей Игоревич
Мне вот тут выше посоветовали вызывать финальную процедуру только тогда, когда счетчик потоков дойдет до нужного (и тут я косякнул и наловил проблем с тем, что счетчик мог понизиться сразу у всех потоков и все потоки бы вызвали процедуры, но это я победил, наверно)
Вы же вот так 22022741 делали? Правда?

Не совсем так, у меня код чуть помудренее, ну я там накосячил и уже сам поправил, но теперь вообще всё хочу фундаментально переделать :). (Хочу отдельный поток, который будет запускать другие потоки по очереди и по завершении последнего уже вызывать событие, просто иначе слишком сложные пересечения сообщений и событий в коде между потоками, я просто тону в них)
Док
Zelius
можно не заморачиваться и сделать SendMessage

а еще можно вызвать потокобезопасные Synchronize/Queue. Немного не изящно, но надежно :)

Синхронайз же будет зависеть от "свободности" главного потока - не хотелось бы, Queue - по не знаю что это пока. (Пока, если честно, как раз через синхронайз и message и передаю данные между потоками, но хочу переделать).
Думаю начать освоение применения критической секции, но как я понимаю, для передачи сообщений она не подходит :).
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906022
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Кстати, а можно ли как-то форму целиком запихнуть в отдельный поток, или это слишком сложно, и ну его нафиг?

GUI всегда в основном потоке и только в нём.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906056
Zelius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

переполниться может. из MSDN про PostMessage:
авторIf the function fails, the return value is zero. To get extended error information, call GetLastError. GetLastError returns ERROR_NOT_ENOUGH_QUOTA when the limit is hit.
так что надо результат отправки обрабатывать. по умолчанию лимит 10 000.

кроме Synchronize есть еще TThread.Queue
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906198
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
GUI всегда в основном потоке и только в нём.
Не всегда. Но это достаточно геморройно
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906258
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич

Пока не очень дружил с указателями. Правильно же?

...

Но возникает вопрос два вопроса, первый может ли очередь формируемая PostMessage переполниться (например принимающий поток сильно занят) и к чему это приведет? Если сообщение "не доходит" по тем или иным причинам - не будет ли утечки памяти, так как код "Dispose" у нас только в принимающем обработчике.

Правильно, только лучше не называть переменные по имени типа (PReal), типы-указатели уже объявлены (^string => PString), и приводить в PostMessage лучше не Integer(), а W/LPARAM().
Вопросы хорошие, очередь конечно может переполниться, т.ч. надо всегда делать
Код: pascal
1.
2.
if not PostMessage then
  Dispose(p)
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906407
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Синхронайз же будет зависеть от "свободности" главного потока - не хотелось бы, Queue - по не знаю что это пока. (Пока, если честно, как раз через синхронайз и message и передаю данные между потоками, но хочу переделать).

чтобы не заморачиваться: Synchronize - потокобезопасный "SendMessage"; Queue - потокобезопасный "PostMessage". И тот, и другой методы позволяют вызывать процедуру доп.потока, где идет работа с основным потоком. Как-то так:



В аттаче говнокод, просто для иллюстрации.

зы. проект собран на DXE (в семерке Queue еще нет, пусть картинка не вводит в заблуждение :) )
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906558
Док,

Нужная штука, но, блин, плохо что в 7 нет. Уж больно мне интерфейс 7ки нравиться (точнее 10ки не нравиться, а перебирать разные версии в поисках хорошей как-то не хочется).

А такой вопрос, в каком потоке будет выполнена процедура CallProcedure

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
var
   Thread1:TThread1; 
   Thread2:TThread2; 

//вызываемая процедура
Procedure TTread1.CallProcedure;
Begin
//какой-нибудь код
End; 

Procedure TThread2.Execute;
Begin
Thread1.CallProcedure; //в каком потоке будет выполнен код внутри процедуры?
end;



И как правильно передавать сообщение уже между отдельными потоками, а не между главным и второстепенными? Просто на форуме видел фразу "вызвать процедуру соответствующего потока, она точна в нужном потоке будет выполнена?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906562
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Код: pascal
1.
2.
3.
4.
Procedure TThread2.Execute;
Begin
Thread1.CallProcedure; //в каком потоке будет выполнен код внутри процедуры?
end;

Thread2
Андрей Игоревич
И как правильно передавать сообщение уже между отдельными потоками
Зависит от того, какие именно сообщения. Первое, что приходит в голову - PostThreadMessage(). Но поток должен ждать сообщения. Само по себе работать не будет
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906864
Zelius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Док,

Нужная штука, но, блин, плохо что в 7 нет. Уж больно мне интерфейс 7ки нравиться (точнее 10ки не нравиться, а перебирать разные версии в поисках хорошей как-то не хочется).

ИМХО, зря, лучше перейти на новое и привыкнуть. в новых дельфах очень много полезного. один юникод чего стоит с TEncoding... Delphi 7 только для легаси, только то что трогать боязно...

Второе, что приходить в голову, это использовать дельфевые очереди, тогда с виндовой не надо заморачиваться. Поставил в TThreadedQueue сообщение, а поток сам его заберет когда освободится.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906959
Zelius
Андрей Игоревич
Док,

Нужная штука, но, блин, плохо что в 7 нет. Уж больно мне интерфейс 7ки нравиться (точнее 10ки не нравиться, а перебирать разные версии в поисках хорошей как-то не хочется).

ИМХО, зря, лучше перейти на новое и привыкнуть. в новых дельфах очень много полезного. один юникод чего стоит с TEncoding... Delphi 7 только для легаси, только то что трогать боязно...

Второе, что приходить в голову, это использовать дельфевые очереди, тогда с виндовой не надо заморачиваться. Поставил в TThreadedQueue сообщение, а поток сам его заберет когда освободится.

Видимо придется, так как в 7ке вот такой код (код чисто тестовый, искал ошибку и тут нашел)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
//это крутиться не в главном потоке, но, наверняка, главный поток не успевал обработать все сообщения
While 0=1 do 
 begin
   Tread:=TThread.Create(false);
   sleep (10);
 end;

...
TThread.Create (..)
Var
 p:Pointer;
Begin
  New(p);
  if not PostMessage(.,.,.,.,.) then Dispose(p);
end;

Почти сразу вылетает с ошибкой конца памяти (при том, что в дипетчере программа занимает жалкие мегабайты (даже с учётом некорректности диспетчера - всё равно мало));

В 10ке (ну или всё дело в 64х) такой код крутиться вечно...

Ну значит скоро будет от меня темы: "а как в 10ке сделать всё красиво?" "а почему в х64 компилятор нельзя остановить на строке" и т.п. :)
Мне бы хотя бы автоматическое дописывание переменных, их выделение в коде всех сразу и исправление их по Enter согласно написанbю в var, уж больно я к этому привык, жуть как помогает, в мечтах я бы вообще хотел делать код разноцветным, мол "критический код", "проверенный", "доработать", "временный" и прочее подобное, комментарии это конечно круто, но цвета - круче, никто такого не делал под 10ку?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39906993
Zelius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

тут ничего не понятно (while 0 = 1), много потоков?

на конец памяти влияет подход s := s + 'abc'... в больших циклах
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907009
Zelius
Андрей Игоревич,

тут ничего не понятно (while 0 = 1), много потоков?

Та я это от балды написал, чтоб показать, что цикл бесконечный. По идее, даже с таким циклом всё равно код
Код: pascal
1.
2.
New(p);
  if not PostMessage(.,.,.,.,.) then Dispose(p);


Должен корректно, хоть и бесконечно работать. (в приемке сообщений Dispose(p) естественно есть).
а, тупанул, забыл про FreeAndNil написать,
В упрощенном формате:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
While 0=1 do 
 begin
   Tread:=TThread.Create(false);
   Tread.WaitFor;
   FreeAndNil(Tread);
   sleep (10);
 end;



ну по сути код а реальности вот так он выглядит в реальности
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  for i:=0 to InListResultLoad.Count-1 do
    begin
              OpenResultFilesInTread:=TOpenResultFiles.Create(InListResultLoad[i],Integer(InListResultLoad.Objects[i]), False);    //поток считывания результатов
              OpenResultFilesInTread.OnCurentResultLoad:=   CoreShell.OnOpenCurrentFile;    //события выгрузки результатов
              OpenResultFilesInTread.OnSelectedResultLoad:= CoreShell.OnOpenSelectedFile;   //события выгрузки результатов
              OpenResultFilesInTread.Resume;
              OpenResultFilesInTread.WaitFor;    //ждем выполненения
              FreeAndNil(OpenResultFilesInTread);  //убиваем законченный
              sleep(10); ждем всякого на всякий
    end;




Как уже написал, в 7ке вылетает с нехваткой памяти, в 10ке и после многих сотен тысяч операций - работало.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907037
Zelius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

а какое кол-во потоков в момент вылета?

ну и просто на предмет утечек посмотреть стоит, как там его... ReportmemoryLeaksOnExit что ли ..
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907038
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич

ну по сути код а реальности вот так он выглядит в реальности
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  for i:=0 to InListResultLoad.Count-1 do
    begin
              OpenResultFilesInTread:=TOpenResultFiles.Create(InListResultLoad[i],Integer(InListResultLoad.Objects[i]), False);    //поток считывания результатов
              OpenResultFilesInTread.OnCurentResultLoad:=   CoreShell.OnOpenCurrentFile;    //события выгрузки результатов
              OpenResultFilesInTread.OnSelectedResultLoad:= CoreShell.OnOpenSelectedFile;   //события выгрузки результатов
              OpenResultFilesInTread.Resume;
              OpenResultFilesInTread.WaitFor;    //ждем выполненения
              FreeAndNil(OpenResultFilesInTread);  //убиваем законченный
              sleep(10); ждем всякого на всякий
    end;




Как уже написал, в 7ке вылетает с нехваткой памяти, в 10ке и после многих сотен тысяч операций - работало.

А какой смысл в этом коде, если каждого потока приходится ждать?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907044
Василий 2
Андрей Игоревич

ну по сути код а реальности вот так он выглядит в реальности
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  for i:=0 to InListResultLoad.Count-1 do
    begin
              OpenResultFilesInTread:=TOpenResultFiles.Create(InListResultLoad[i],Integer(InListResultLoad.Objects[i]), False);    //поток считывания результатов
              OpenResultFilesInTread.OnCurentResultLoad:=   CoreShell.OnOpenCurrentFile;    //события выгрузки результатов
              OpenResultFilesInTread.OnSelectedResultLoad:= CoreShell.OnOpenSelectedFile;   //события выгрузки результатов
              OpenResultFilesInTread.Resume;
              OpenResultFilesInTread.WaitFor;    //ждем выполненения
              FreeAndNil(OpenResultFilesInTread);  //убиваем законченный
              sleep(10); ждем всякого на всякий
    end;




Как уже написал, в 7ке вылетает с нехваткой памяти, в 10ке и после многих сотен тысяч операций - работало.

А какой смысл в этом коде, если каждого потока приходится ждать?

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


В общем потоки, это сложно (для меня), но интересно.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907045
Zelius
Андрей Игоревич,

а какое кол-во потоков в момент вылета?

ну и просто на предмет утечек посмотреть стоит, как там его... ReportmemoryLeaksOnExit что ли ..

Потоки сразу убиваются, они поочередно запускаются (просто сразу забыл об этом написал), просто, видимо Postmessage забивала всю очередь и выдавало такую ошибку (ну я предполагаю), в delphi 10ке такого нет.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907140
Zelius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

все это звучит странно, не должно быть такой разницы... да и "видимо" не дает гарантий что так и было. ну да ладно, дело хозяйское )
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907171
Zelius
Андрей Игоревич,

все это звучит странно, не должно быть такой разницы... да и "видимо" не дает гарантий что так и было. ну да ладно, дело хозяйское )

"Видимо" это я просто предположил, код 100% идентичный, по сути одни и те же модули запускаю из под разных Делфи.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907199
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

я так понимаю, вопросы лицензионной чистоты тебя не очень заботят? Лишь бы была дельфя?

Зря ты с семеркой мучаешься. Возьми на руборде портабельную сборку (последняя "рабочая" там была то ли DXE, то ли DXE2). Они не требуют установки, легко регятся идущими в комплекте генераторами, поддерживают юникод и проч."радости". Если надо, могу кинуть ссылкой
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907271
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Код: pascal
1.
2.
3.
4.
5.
6.
7.
While 0=1 do 
 begin
   Tread:=TThread.Create(false);
   Tread.WaitFor;
   FreeAndNil(Tread);
   sleep (10);
 end;

Где в этом коде опрос очереди сообщений, чтобы достать ваши PostMessage?
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39907321
_Vasilisk_
Андрей Игоревич
Код: pascal
1.
2.
3.
4.
5.
6.
7.
While 0=1 do 
 begin
   Tread:=TThread.Create(false);
   Tread.WaitFor;
   FreeAndNil(Tread);
   sleep (10);
 end;

Где в этом коде опрос очереди сообщений, чтобы достать ваши PostMessage?

Прием постмесаджей в главном потоке, просто не привел. Та фиг с ним, работает на 10ке (проверил на десятке миллионов циклов) и ладно. Может потом попробую понять почему (хотя будет сложно, если оно работает)
Док
Андрей Игоревич,

я так понимаю, вопросы лицензионной чистоты тебя не очень заботят? Лишь бы была дельфя?

Зря ты с семеркой мучаешься. Возьми на руборде портабельную сборку (последняя "рабочая" там была то ли DXE, то ли DXE2). Они не требуют установки, легко регятся идущими в комплекте генераторами, поддерживают юникод и проч."радости". Если надо, могу кинуть ссылкой

После нового года займусь изучением вопроса.
...
Рейтинг: 0 / 0
Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
    #39918569
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

на штучку наткнулся, есть много переходников
https://tiledb.com/
...
Рейтинг: 0 / 0
135 сообщений из 135, показаны все 6 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Много малых вопросов о работе с памятью при работе с динамическими массивами и классами.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]