Падение QUIK с 0xC0000005: Access violation

Страницы: 1
RSS
Падение QUIK с 0xC0000005: Access violation
 
Проблема происходит в lua скрипте, который реализует заявки по волатильности для опционов. Скрипт запускает в main() таймер, который срабатывает через 500ms и пересчитывает новые цены лимитных заявок опционов в соответствии с текущей ценой фьючерса. Если цена для опциона изменилась, то заявка передвигается - делается sendTransaction (["ACTION"] = "MOVE_ORDERS"). Коллбэк на таймер срабатывает в том же потоке, что и main().

Также скрипт подписан на коллбэк OnTransReply для получения информации о передвижении заявки.

Для UI используется iup.
Версия QUIK: 7.5.0.72

Это скрипт корректно работает, но не долго. Где-то через 5 -20 минут QUIK падает с ошибкой:
Код
First-chance exception at 0x6D8AEEE2 (qlua.dll) in info.exe: 0xC0000005: Access violation reading location 0x8B0C77A3.

Я сделал трейсинг в скрипте, но проблема в том, что падение происходит в произвольном месте. Т.е. нет определенной точки в коде, которая приводит к ошибке. Падение происходит не в потоке обрабатывающим таймер, а в главном потоке QUIK, который вызывает коллбэки.  Т.е. что-то просто отваливается в самом QLUA.

Могу выслать сам код для того чтобы воспроизвести ошибку.

Фрагмент лога одного из падений (скрипт перед этим минут 20 нормально работал):
Код
main_timer:action_cb():1
main_timer:action_cb():2
recalcOrders():1
recalcOrders():2
recalcOrders():3
recalcOrders():4
recalcOrders():5
recalcOrders():6
recalcOrders():7
recalcOrders():8
recalcOrders():9
recalcOrders():10
recalcOrders():11
recalcOrders():12
recalcOrders():13
recalcOrders():14
recalcOrders():15
recalcOrders():16
recalcOrders():2
recalcOrders():3
recalcOrders():4
recalcOrders():5
recalcOrders():6
recalcOrders():7
recalcOrders():8
recalcOrders():9
recalcOrders():10
recalcOrders():11
recalcOrders():12
recalcOrders():13
recalcOrders():14
recalcOrders():15
recalcOrders():16
recalcOrders():2
recalcOrders():3
recalcOrders():4
recalcOrders():5
recalcOrders():6
recalcOrders():7
recalcOrders():8
recalcOrders():9
recalcOrders():10
recalcOrders():11
recalcOrders():12
recalcOrders():13
recalcOrders():14
recalcOrders():15
recalcOrders():16
recalcOrders():2
recalcOrders():3
recalcOrders():4
recalcOrders():5
recalcOrders():6
recalcOrders():7
recalcOrders():8
recalcOrders():9
recalcOrders():10
recalcOrders():11
recalcOrders():12
OnTransReply():begin
OnTransReply():end
recalcOrders():13
recalcOrders():14
recalcOrders():15
recalcOrders():16
recalcOrders():2
recalcOrders():3
recalcOrders():4
First-chance exception at 0x6D8AEEE2 (qlua.dll) in info.exe: 0xC0000005: Access violation reading location 0x8B0C77A3.
recalcOrders():5
Unhandled exception at 0x6D8AEEE2 (qlua.dll) in info.exe: 0xC000041D: An unhandled exception was encountered during a user callback.
 
The program '[852] info.exe' has exited with code 0 (0x0).



 
 
Добрый день,

Для диагностики проблемы просьба направить запрос на адрес: quiksupport@arqatech.com указав в письме ссылку на данную ветку форума.
В письме нужно приложить используемый скрипт, а также файлы дампа, которые расположены в папке QUIK, подпапке /dmp.
 
Отправил код скрипта с библиотеками. Дамп QUIK не создает.
 
В итоге после пересылки кода в поддержке QUIK воспроизвести падение не смогли, но предположили, что, скорее всего, проблема из-за того, что в скрипте для GUI используется IUP.

Вроде как использование сторонних библиотек для интерфейса, таких как IUP или WX, в QUIK не рекомендуется. В связи с этим вопрос, а что тогда использовать, если нужен интерфейс чуть больше чем одна таблица?

Может тогда лучший вариант сразу весь код торгового робота писать на C++/C#, а код lua делать из единственной строчки:
Код
require(“My_Dll_Which_Does_the_Job”)
 
 
IUP уже написана на С++
так что не особо обольщайтесь таким вариантом. Ну т.е. волшебства не будет.
кстати, попробуйте QVcl
может в вашей задаче будет стабильнее

https://quik2dde.ru/viewtopic.php?id=111
 
Цитата
philave написал:
В итоге после пересылки кода в поддержке QUIK воспроизвести падение не смогли, но предположили, что, скорее всего, проблема из-за того, что в скрипте для GUI используется IUP.
Знакомая песня. Поддержка всегда валит вину на кого-то другого, пока не "припрёшь их к стенке".
Но из собственного опыта скажу, что у меня падения происходили чаще из-за ошибок в самом QLua.

Цитата
philave написал:
Скрипт запускает в main() таймер
Цитата
philave написал:
Коллбэк на таймер срабатывает в том же потоке, что и main().
Может быть дело в этом? А библиотека в каком потоке подключается? UI в каком потоке строится?
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Старатель написал:
Знакомая песня. Поддержка всегда валит вину на кого-то другого, пока не "припрёшь их к стенке".
Очень похоже поддержка права. Я сделал тестовый скрипт, который реализует тот же функционал, но без интерфейса и без IUP - QUIK перестал падать.
Цитата
Старатель написал:
Может быть дело в этом? А библиотека в каком потоке подключается? UI в каком потоке строится?
Библиотека подключается в процессе info.exe - это код и он один на все потоки.
А UI строится в том же main. Код main выглядит вот так:
Код
function main() -- Функция, реализующая основной поток 
                message("main:"..luawin.GetCurrentThreadId(), 2)
 
                if isConnected() == 0 then -- Скрипт не запускается если QUIK не подключен
                                return
                end 
 
                dlg_main:showxy(iup.CENTER, iup.CENTER) -- Показываем главное окно со списком заявок
                main_timer.run = "YES" -- Запускаем поток обработки заявок
                iup.MainLoop() -- Здесь этот поток зависает пока не будет закрыто главное окно или остановлен скрипт из QUIK
                main_timer.run = "NO" -- Останавливаем поток обработки заявок
                cancelAllOrders() -- Посылаем сигнал на снятие всех заявок. Ждать результата уже не будем
                iup.ExitLoop()
                iup.Close()
end
Здесь iup.MainLoop() разгребает очередь сообщений UI. События на вызов таймера приходят в эту же очередь. Судя по логу callback таймера всегда вызывается в том же потоке, что и main.
 
philave,
Попробуйте перенести работу с UI в основной поток терминала.
К тому же я вижу, что вы используете luawin. Возможно, это тоже как-то влияет.
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Библиотека подключается в процессе info.exe - это код и он один на все потоки.
А UI строится в том же main.
никогда не истользуйте. UI в дополнительном потоке.
глюки гарантированы и это объяснимо.
 
Цитата
Старатель написал:
philave  ,
Попробуйте перенести работу с UI в основной поток терминала.

Спасибо за совет!
Перенес обработку UI в главный поток QUIK и, очень похоже, это помогло. Проблема заявленная в теме ушла – по крайней мере сейчас 2 часа гонял и ее не удалось ее воспроизвести.

Правда появилась другая проблема – сейчас скрипт не возможно остановить не обрушив QUIK. Но это уже другая история. Надеюсь это удастся поправить.


Цитата
swerg написал:
Цитата
Библиотека подключается в процессе info.exe - это код и он один на все потоки.
А UI строится в том же main.
никогда не истользуйте. UI в дополнительном потоке.
глюки гарантированы и это объяснимо.

А можете в двух словах объяснить почему? Как-то это не очевидно и более того, мне кажется, архитектурно правильнее делать в отдельном потоке main свой UI.
 
Цитата
philave написал:
Цитата
А можете в двух словах объяснить почему? Как-то это не очевидно и более того, мне кажется, архитектурно правильнее делать в отдельном потоке main свой UI.
Это очевидно, если вы хоть раз писали цикл обработки сообщений и собственно оконную функцию на WinAPI.
Кроме того, при использовании UI в отдельном потоке вы фактически обращаетесь к "экранным" объектам из разных потоков, т.к. QUIK, как и любое Windows-приложение имеет свой цикл обработки оконных сообщений, т.е. тоже самое, что написано в iup.MainLoop().
Кроме того, вызывать iup.MainLoop() вызывать в основном потоке Квика не следует, если вы запускаете все это хозяйство в QUIK.
Да, когда вы всё перенесете основной поток - то не следует обращаться к iup из кода, работающего в main() скрипта или вызываемого оттуда. Опять же потому, что в iup нет реализации корректной многопоточной работы, она банально для этого не предназначена.
Страницы: 1
Читают тему
Наверх