Поскольку известно, что в Lua 5.4.1 есть неприятный баг
исправленный в Lua 5.4.2, имеет смысл поднять версию внутри QUIK.
Пользователь
Сообщений: Регистрация: 31.01.2015
22.12.2020 14:47:25
Заходит пациент в кабинет к доктору. -- На что жалуетесь? -- Доктор, меня все игнорируют. -- Следующий.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
06.01.2021 11:25:27
Существует ненулевая вероятность, что сборщик придёт как раз во время обхода таблицы в одном из потоков.
Скрытый текст
Код
local p = {}
function OnParam(class_code, sec_code)
p[sec_code] = class_code
end
local t = {}
function OnAllTrade(alltrade)
t[alltrade.sec_code] = alltrade.class_code
end
function main()
while run do
for k, v in pairs(p) do
p[k] = nil
end
for k, v in pairs(t) do
t[k] = nil
end
sleep(1)
end
end
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 31.01.2015
07.01.2021 08:13:21
Этот тест воспроизводит ошибку? Если да, то разработчикам, всё-таки, стоит зарегистрировать пожелание.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
07.01.2021 09:40:25
В Lua 5.3 и Lua 5.4:
Цитата
invalid key to 'next'
Надо делать так, как надо. А как не надо - делать не надо.
У себя подобного за целый день не увидели, можете предоставить снимки экрана?
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
08.01.2021 17:34:38
Цитата
Roman Azarov написал: С некоторой вероятностью может появиться следующая ошибка?
Верно
Цитата
Roman Azarov написал: У себя подобного за целый день не увидели
Можете форсировать события:
Скрытый текст
Код
local p = {}
function OnParam(class_code, sec_code)
for i = 1, 20 do
p[sec_code..i] = class_code
end
end
local t = {}
function OnAllTrade(alltrade)
for i = 1, 20 do
t[alltrade.sec_code..i] = alltrade
end
end
function main()
while run do
for k, v in pairs(p) do
p[k] = nil
end
for k, v in pairs(t) do
t[k] = nil
end
sleep(1)
end
end
и сделать перезаказ всех обезличенных сделок.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
09.01.2021 14:23:47
Чтобы обход таблицы был более корректным, изменим тестовый скрипт, так, чтобы добавление и удаление полей таблицы осуществлялось в одном потоке:
Скрытый текст
Код
local run = true
function OnStop()
run = nil
end
local function f(t)
for i = 1, 100 do
t[""..i] = i
end
for k, v in pairs(t) do
t[k] = nil
end
t = {}
return t
end
p = {}
function OnParam(class_code, sec_code)
p = f(p)
end
a = {}
function OnAllTrade(alltrade)
a = f(a)
end
m = {}
function main()
while run do
m = f(m)
sleep(1)
end
end
Ошибка "invalid key to 'next'" никуда не делась. Для форсирования: перезаказать все обезличенные сделки.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
18.01.2021 19:19:49
На самом деле, при использовании в боевом скрипте внутри цикла pairs, ещё много операций, а иначе зачем он нужен? Типа:
Код
for sec_code, class_code in pairs(p) do
p[sec_code] = nil
local last = tonumber(getParamEx2(class_code, sec_code, "LAST"))
...
end
И тогда ошибка возникает практически сразу (без форсирования). В таком случае, чтобы избежать ошибки, таблицу лучше обходить через next.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
18.04.2021 11:06:08
QUIK 8.13.1.16, Lua 5.4 Получил очередную ошибку
Цитата
invalid key to 'next'
в древнем скрипте
Код
local ID = {}
function main()
...
for TableName, id in pairs(ID) do
ID[TableName] = nil
DestroyTable(id)
end
...
end
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 30.01.2015
18.04.2021 11:08:58
Цитата
Старатель написал: QUIK 8.13.1.16, Lua 5.4 Получил очередную ошибку
Цитата
invalid key to 'next'
в древнем скрипте
Код
local ID = {}
function main ()
.. .
for TableName, id in pairs(ID) do
ID[TableName] = nil
DestroyTable (id)
end
.. .
end
с функцией next проблемы давние, в 5.3 тоже присутствуют.
Пасхалочка для Алексея Иванникова:
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
18.04.2021 11:36:09
Придётся вот таким "изящным" способом обходить:
Код
repeat
local k, v = next(t)
if k == nil then break end
t[k] = nil
until false
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 03.02.2021
18.04.2021 12:47:13
Если у вас колбеки могут изменять столы, то нужно пользоваться потокобезопасными функциями.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
18.04.2021 13:14:55
Цитата
Артем написал: нужно пользоваться потокобезопасными функциями
Хотелось бы увидеть пример потокобезопасной функции для обхода ассоциативного массива. Или вы предлагаете весь цикл в ssort запихать?
Не знаю, какие "столы", но с сообщения #8 работа с таблицей - в одном потоке. Впрочем, это по видно.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 03.02.2021
18.04.2021 15:16:51
Старатель, ходить по массиву можно обычными функциями, а удалять/добавлять значения надо потокобезопасными. Вообще, удалять значения из массива в цикле по этому же массиву это плохая практика; вы тут судя по всему просто очищаете стол, вместо этого можно просто создать пустой - это не только надежнее и проще, но еще и работает быстрее.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
18.04.2021 15:57:40
Цитата
Артем написал: удалять/добавлять значения надо потокобезопасными
Какой, например, функцией для ассоциативного массива? И почему?
Цитата
Артем написал: удалять значения из массива в цикле по этому же массиву это плохая практика
Цитата
Артем написал: просто создать пустой - это не только надежнее и проще
Можете обосновать каждое своё утверждение?
Надо делать так, как надо. А как не надо - делать не надо.
Ну ляпнули вы ерунду один раз. Зачем дальше-то показывать свою глупость? К вам вопросов больше не имею.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 03.02.2021
19.04.2021 09:15:22
Старатель, посты тех кто жалуется на язык читаю про диагонали.
Очистить стол - N операций вм и N операций гц. Заменить пустым - 1 операция вм и N+1 операций гц.
То что вам поенепременно надо использовать непотокобезопасные методы в многопоточной программе - тут что называется своих мозгов в чужую голову не вставишь.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
19.04.2021 10:35:42
Цитата
Артем написал: удалять значения из массива в цикле по этому же массиву это плохая практика
В Lua не запрещено, из Reference Manual:
Цитата
The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may set existing fields to nil.
Ошибка, обсуждаемая в ветке, может возникнуть при работе с таблицей в одном потоке. При чём здесь вообще потокобезопасные функции, которые к тому же, не работают с ассоциативными массивами?
Столы - в мебельном. А здесь - таблицы, и в таблице могут очищаться не все значения:
Код
for k, v in pairs(t) do
if exp then t[k] = nil end
end
Создавать новую таблицу под каждое очищаемое значение - это бред.
Артем, если вы, кроме "патамушта гладиолус небо голубое", не можете ничем аргументировать, то у меня к вам нет вопросов.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 03.02.2021
19.04.2021 12:41:57
Старатель, аргументы я привел, вы их благополучно проигнорировали. Тут что называется нами три типа людей: есть джентльмены которые соглашаются, есть обезьяны которые начинают спорить с задокументированными и/или воспроизводимыми вещами, и есть такие вот индивиды которые просто делают вид что ничего сказано и не было. Неприятно когда просишь обосновать что-то думая что умнее всех и никто ничего не скажет, а кто-то берет и обосновывает, понимаю.
Совет от профи: просто не работайте с одной и той же памятью из разных тредов, вот и все. В луа конечно мутексов нету, уж не предусмотрено многопоточности на уровне вм, просто в арке люди слову на глобус натягивают. Но вам родина нафига двойную буферизацию дала?
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
19.04.2021 13:31:31
Артем, джентльмены соглашаются только с тем, кто прав. А умников, которые считают себя "профи" в каждом вопросе, а по факту даже не понимают сути обсуждаемого, надо на место ставить.
Что вы там обосновали? Про "небо голубое"? Аргументов от вас лично я так и не увидел.
Цитата
Артем написал: просто не работайте с одной и той же памятью из разных тредов
Спасибо, кэп, без вас бы не разобрались. Ветка про другое. Второй поток вообще может не знать про таблицу в первом, или может знать, но не работать с ней.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
19.04.2021 18:57:42
Цитата
Roman Azarov написал: У себя подобного за целый день не увидели
Roman Azarov, вот тест, который воспроизводит ошибку практически сразу после перезаказа обезличенных сделок.
Скрытый текст
Можете поиграться со значением параметра n
Код
local n = 25
local run = true
function OnStop()
run = nil
end
function OnParam(class_code, sec_code)
p = {}
for i = 1, n do
p[tostring(i)] = tostring(i)
end
for k, v in pairs(p) do
p[k] = os.time()
p[k] = nil
end
end
function OnAllTrade(alltrade)
a = {}
for i = 1, n do
a[tostring(i)] = tostring(i)
end
for k, v in pairs(a) do
a[k] = os.time()
a[k] = nil
end
end
function main()
while run do
m = {}
for i = 1, n do
m[tostring(i)] = tostring(i)
end
for k, v in pairs(m) do
m[k] = os.time()
m[k] = nil
end
sleep(1)
end
end
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 31.01.2015
20.04.2021 10:22:37
Тем временем, в Lua 5.4 продолжают находить баги. Так что если разработчики, всё-таки, будут обновлять версию, то просьба до самой последней обновить.
Пользователь
Сообщений: Регистрация: 03.02.2021
20.04.2021 17:40:23
Баги были есть и будут. Тут есть два подхода: постоянно обновляться до самой свежей версии, в процессе чего что-то может сломаться, либо выбрать версию и сидеть на ней всё обозримое будущее, а с багами люди разберутся на месте.
написал: У себя подобного за целый день не увидели
, вот тест, который воспроизводит ошибку практически сразу после перезаказа обезличенных сделок. Скрытый текст Можете поиграться со значением параметра n
Код
local n = 25
local run = true
function OnStop ()
run = nil
end
function OnParam (class_code, sec_code)
p = {}
for i = 1 , n do
p[tostring(i)] = tostring(i)
end
for k, v in pairs(p) do
p[k] = os.time ()
p[k] = nil
end
end
function OnAllTrade (alltrade)
a = {}
for i = 1 , n do
a[tostring(i)] = tostring(i)
end
for k, v in pairs(a) do
a[k] = os.time ()
a[k] = nil
end
end
function main ()
while run do
m = {}
for i = 1 , n do
m[tostring(i)] = tostring(i)
end
for k, v in pairs(m) do
m[k] = os.time ()
m[k] = nil
end
sleep ( 1 )
end
end
Добрый день,
Действительно, в ПО QLUA есть ошибка функций обратного вызова скрипта приводящая к подобным ошибкам. Мы справим её в очередном обновлении ПО приносим извинения за причинённые неудобства.