Добрый день.
Буду признателен за помощь!
На QLUA создаю пользовательскую табличку, на которую при помощи функции SetTableNotificationCallback вешаю обработчик нажатий клавиш. По нажатию ПРОБЕЛ обработчик должен запросить некоторые данные из таблиц QUIK и отобразить их в таблице. Обработчик использует только локальные переменные, которые, по идее, должны быть освобождены после выхода из обработчика, однако, если в окне (Меню Сервисы -> Lua скрипты... -> Окно Доступные скрипты) пронаблюдать динамику объёма памяти, который скрипт занимает, то видно, что при каждом нажатии пробела (т.е. при каждом вызове обработчика) объем занятой памяти только равномерно увеличивается, но никогда не освобождается. Исходник ниже, достаточно его просто Copy/Paste к себе, чтобы воспроизвести проблему.
Буду признателен за помощь!
На QLUA создаю пользовательскую табличку, на которую при помощи функции SetTableNotificationCallback вешаю обработчик нажатий клавиш. По нажатию ПРОБЕЛ обработчик должен запросить некоторые данные из таблиц QUIK и отобразить их в таблице. Обработчик использует только локальные переменные, которые, по идее, должны быть освобождены после выхода из обработчика, однако, если в окне (Меню Сервисы -> Lua скрипты... -> Окно Доступные скрипты) пронаблюдать динамику объёма памяти, который скрипт занимает, то видно, что при каждом нажатии пробела (т.е. при каждом вызове обработчика) объем занятой памяти только равномерно увеличивается, но никогда не освобождается. Исходник ниже, достаточно его просто Copy/Paste к себе, чтобы воспроизвести проблему.
Код |
---|
-- ************************************************ -- * Обработчик событий для таблицы * -- ************************************************ function UpdateTableData(t_id, msg, par1, par2) if msg == QTABLE_VKEY and par2 == 32 then -- нажата клавиша "Пробел", local records = {} local i = 0 local option_class_code = "SPBOPT" local ba_sec_code = "RIM4" local sec_list = getClassSecurities(option_class_code) for option_sec_code in string.gmatch(sec_list, "([%.%w]+)") do local securityInfo = getSecurityInfo(option_class_code, option_sec_code) if securityInfo ~= nil and securityInfo.base_active_seccode == ba_sec_code and 20240501 < securityInfo.exp_date then local sec_type = getParamEx(option_class_code, option_sec_code, "OPTIONTYPE").param_image if sec_type == "Put" then i = i + 1 local type_execution = getParamEx(option_class_code, option_sec_code, "OPTIONEXECTYPE").param_image records[i] = { ba_sec_code = ba_sec_code, option_sec_code = option_sec_code, option_sec_code_full = securityInfo.name, option_class_code = option_class_code, exp_date = securityInfo.exp_date, ba_class = "SPBFUT", vid_option = "Американский", type_execution = type_execution, option_strike = securityInfo.option_strike, format = "%." .. securityInfo.scale .. "f", } end -- sec_type end -- if securityInfo end -- for option_sec_code -- -- Now draw the table Clear(Tt_id) for k,v in pairs(records) do InsertRow(Tt_id, k) SetCell(Tt_id, k, 1, v.ba_sec_code) SetCell(Tt_id, k, 2, v.ba_class) SetCell(Tt_id, k, 3, v.option_sec_code_full) SetCell(Tt_id, k, 4, v.option_sec_code) SetCell(Tt_id, k, 5, v.option_class_code) SetCell(Tt_id, k, 6, string.sub(v.exp_date , 7,8) .. "." .. string.sub(v.exp_date , 5, 6) .. "." .. string.sub(v.exp_date , 1, 4)) SetCell(Tt_id, k, 7, v.vid_option) SetCell(Tt_id, k, 10, v.type_execution) end -- for k,v SetSelectedRow(Tt_id, 1) -- установить курсор на запись-чемпиона end -- if msg == QTABLE_CHAR end -- UpdateTableData -- ********************************************* -- * Обарботчик запуска скрипта * -- ********************************************* function OnInit(script_path) Tt_id = AllocTable() AddColumn(Tt_id, 1, "Б.А.", true, QTABLE_STRING_TYPE, 10) AddColumn(Tt_id, 2, "Б.А.Класс", true, QTABLE_STRING_TYPE, 15) AddColumn(Tt_id, 3, "Код инструмента (полн.)", true, QTABLE_STRING_TYPE, 25) AddColumn(Tt_id, 4, "Код инструмента", true, QTABLE_STRING_TYPE, 15) AddColumn(Tt_id, 5, "Код Класса", true, QTABLE_STRING_TYPE, 10) AddColumn(Tt_id, 6, "Погашение", true, QTABLE_DATE_TYPE, 10) AddColumn(Tt_id, 7, "Вид опциона", true, QTABLE_STRING_TYPE, 15) -- Американский / Европейский AddColumn(Tt_id, 8, "Тип опциона", true, QTABLE_STRING_TYPE, 5) -- Call / Put AddColumn(Tt_id, 9, "Тип расчёта", true, QTABLE_STRING_TYPE, 15) -- Маржа / Премия AddColumn(Tt_id, 10, "Тип исполнения", true, QTABLE_STRING_TYPE, 12) -- Поставка / Расчёт AddColumn(Tt_id, 11, "Страйк", true, QTABLE_DOUBLE_TYPE, 12) AddColumn(Tt_id, 12, "Цель", true, QTABLE_DOUBLE_TYPE, 12) AddColumn(Tt_id, 13, "Профит, пт", true, QTABLE_INT_TYPE , 12) AddColumn(Tt_id, 14, "Теор. цена", true, QTABLE_DOUBLE_TYPE, 12) AddColumn(Tt_id, 15, "Доходность", true, QTABLE_DOUBLE_TYPE, 8) CreateWindow(Tt_id) SetTableNotificationCallback(Tt_id, UpdateTableData) SetWindowCaption(Tt_id, "test 1.0") SetWindowPos(Tt_id, 1, 259, 1500, 655) InsertRow(Tt_id, -1) -- Зачем-то просят вставить эту запсиь ... end -- OnInit() -- ********************************************* -- * Обарботчик останова скрипта * -- ********************************************* function OnStop() DestroyTable(Tt_id) Tt_id = nil IsRun = false end -- ********************************************* -- * Start running program * -- ********************************************* IsRun = true function main() while IsRun do sleep(1000) end end |
На скрине показан объём занятой памяти в моменте. Для воспроизведения проблемы нужно несколько раз нажать ПРОБЕЛ при нахождении фокуса ввода на таблице и пронаблюдать обведённое красным кружком значение.
Оно увеличивается.
Ожидаемое поведение: последовательное нажатие ПРОБЕЛ и вызов обработчика не приводят к постоянному росту объёма занимаемой памяти.
Буду рад Вашим соображениям как можно решить эту проблему.
С уважением,
Роман.