Добрый день.
Буду признателен за помощь!
На 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
|
На скрине показан объём занятой памяти в моменте. Для воспроизведения проблемы нужно несколько раз нажать ПРОБЕЛ при нахождении фокуса ввода на таблице и пронаблюдать обведённое красным кружком значение.
Оно увеличивается.
Ожидаемое поведение: последовательное нажатие ПРОБЕЛ и вызов обработчика не приводят к постоянному росту объёма занимаемой памяти.
Буду рад Вашим соображениям как можно решить эту проблему.
С уважением,
Роман.