Форум программистов, компьютерный форум, киберфорум
Delphi: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
4 / 4 / 1
Регистрация: 24.01.2023
Сообщений: 20
RAD XE3+

Проблемы с менеджером памяти при слишком частом обращении

08.02.2023, 18:01. Показов 1335. Ответов 3

Студворк — интернет-сервис помощи студентам
Напоролся на неожиданную проблему.
Пишу программу, в которой захватываются два потока видео (с двух видеокарт).
Захват идёт через API, в котором на прибытие кадра приходит callback.
Соответственно, у меня по прибытию кадра создаётся объект, который запихивается в TThreadList. Потом обрабатывается и удаляется. Так как два потока, то у меня 50 раз в секунду создаётся объект и 50 раз в секунду удаляется обработанный объект. Объектов в очереди относительно немного - порядка 1000.
В чём проблема. Пока объекты только создаются (заполнение очереди) - всё отлично.
Как только объекты начинают удаляться, то через некоторое время выпадает exception вида - access violation.
Судя по стеку в момент exception - проблема возникает в момент создания нового объекта - то есть выглядит так, как будто система не может выделить ему память и всё рушится.
Никакой закономерности найти не смог. Возникает такое ощущение, что если слишком часто создавать и удалять объекты, то менеджер памяти начинает сходить с ума. Никто не сталкивался с таким?

Объекты крошечные, объявлены вот таким образом:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
TioAVFrame = class(TOBject)
    VideoData: PByte;
    AudioData: PData16;
    frame_number: Int64;
    start_sample: Int64;
    duration: Int64;
    destructor Destroy; override;
  end;
 
  TTL_outAVframes = TThreadList<TioAVFrame>;
  TL_outAVframes = TList<TioAVFrame>;
 
destructor TioAVFrame.Destroy;
begin
  if Assigned(VideoData) then
    FreeMemory(VideoData);
  if Assigned(AudioData) then
    FreeMemory(AudioData);
 
  VideoData := nil;
  AudioData := nil;
 
  inherited;
end;
В callback'е идёт заполнение:
Delphi
1
2
3
4
5
6
7
8
9
     tmp_frame := TioAVFrame.Create;
 
      tmp_frame.VideoData := nil;
      tmp_frame.AudioData := nil;
      tmp_frame.frame_number := l_frame_number;
      tmp_frame.start_sample := l_sample_number;
      tmp_frame.duration := bufsize;
 
      out_frames.Add(tmp_frame);
Удаление идёт в таймере (пока просто для целей тестирования):
Delphi
1
2
3
4
5
6
7
8
9
10
  tmp_list := Main_in_AVFrames.LockList;
 
  while tmp_list.Count > (10) do
  begin
    tmp_frame := tmp_list.Items[0];
    tmp_list.Delete(0);
 
    if Assigned(tmp_frame) then
      tmp_frame.Free;
  end;
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.02.2023, 18:01
Ответы с готовыми решениями:

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

Проблемы с qtreewidget при частом добавлении айтемов
Здрасти)) Я новичок, так что сильно не пинайте) Задача: в виджет состоящий из нескольких колонок необходимо добавлять строчки из...

Ошибка при обращении к памяти?
Ребята, помогите хоть отследить ошибку. Программа вылетает при больших значений z, хотя каждый раз по разному... Подозреваю, что проблема...

3
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
09.02.2023, 05:52
Цитата Сообщение от An_private Посмотреть сообщение
создаётся объект, который запихивается в TThreadList. Потом обрабатывается и удаляется
Вот тут поподробнее можно?
Кем удаляется, в какой момент и т.п.
По хорошему лучше конечно минимальный рабочий пример, где воспроизводится ошибка.
Потому как по примерам кода
созданные кадры вы пишете в
Delphi
1
 out_frames.Add(tmp_frame);
А удаляете из
Delphi
1
tmp_list
0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,338
09.02.2023, 09:18
Лучший ответ Сообщение было отмечено An_private как решение

Решение

Если callback идёт из драйвера, то эта процедура может работать в другом потоке, и одновременное обращение к одному и тому же объекту вызовет ошибку. Можно попробовать использовать критическую секцию при добавлении и удалении объектов. Только смущает, что добавляется в один список, а удаляется из другого. Как это?
0
4 / 4 / 1
Регистрация: 24.01.2023
Сообщений: 20
09.02.2023, 09:46  [ТС]
Цитата Сообщение от AzAtom Посмотреть сообщение
Если callback идёт из драйвера, то эта процедура может работать в другом потоке
Бинго. Сам пришёл к этому вчера и вечер интенсивного гугления привёл к интересным результатам. Оказывается, у Delphi два менеджера памяти (или это два режима одного - я не понял, но не суть) - и дефолтный не является потокобезопасным!
Дельфи сам определяет режим - если вы явно запускаете из вашего приложения другие потоки, то он переключается на потокобезопасный менеджер памяти. Но в моём случае использования callback'ов недостаточно для этого и менеджер работал не в потокобезопасном режиме.
Оказывается, есть специальный флажок isMultiThread, который по умолчанию ставится самим дельфи. Но его можно поставить и ручками в FormCreate и тогда менеджер памяти принудительно переводится в потокобезопасный режим. Я это сделал и всё сразу заработало нормально (чьорт побьери, целый день угробил на эту проблему).

Цитата Сообщение от AzAtom Посмотреть сообщение
одновременное обращение к одному и тому же объекту вызовет ошибку. Можно попробовать использовать критическую секцию при добавлении и удалении объектов
Я поэтому для хранения и использовал TThreadList - там автоматически создаётся критическая секция с момента LockList до UnlockList. И именно поэтому идёт добавление через TThreadList.Add (он там внутри имеет lock/unlock), а вот удалить элемент из листа можно только через временный TList, который отдаётся при LockList.
Поэтому и выглядит, что это разные листы.
Я постоянно использовал подобное решение во многопоточных приложениях. Но никак не ожидал, что дефолтный memory manager является not thread safe
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.02.2023, 09:46
Помогаю со студенческими работами здесь

Проблемы при обращении в к файлам на Ситевом диске
Доброе время суток! Я написал програмку..неважно...уже крыша кипит Суть проблемы: Программа обращается к некоторому...

Невнятная ошибка при обращении к памяти
Здравствуйте. Вкратце: библиотека наружу выдает структуру entity_t, которая содержит указатель на различные типы объектов, их...

проблемы с Sessions - при обращении из сети переменные сбрасываются...
обращаюсь на web сервер из сети, прохожу регистрацию - все ок, но при переходе на след. страницы сайта сессия сбрасывается. И получается,...

После отключения cdn проблемы с работой ssl при обращении к S3 хранилищу
Добрый день. Проблема такая: Есть сайт, сидит на домене. Есть S3 хранилище, где хранятся массивные статические файлы мультимедиа для...

[MCS51] Инвертирование с использованием косвенно-регистровой адресации при любом обращении к ячейкам памяти
Здравствуйте! Помогите решить задачу: Инвертировать содержимое ячейки памяти и результат поместить в другую ячейку С прямой...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка. Рецензия / Мнение Это мой обзор планшета X220 с точки зрения школьника. Недавно я решила попытаться уменьшить свой. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru