Периодически выводится ошибка "1000". Подскажите, это может значить? Появление ошибки хаотичное.
Мой код в С++
Код
int lua_OnQuote(lua_State *st)
{
int top = _luafix.GetTop();
if (top == 0) return 0;
string sec_code = _luafix.ToString(-1); // код бумаги
string class_code = _luafix.ToString(-2);// код класса
TABLEQuote quote = _luafix.getQuoteLevel2(class_code, sec_code);
_luafix.Pop(1);
_luafix.sendQuote(quote); // здесь отправка стакана в торговый робот
return 0;
}
В данном примере переменная sec_code иногда имеет значение = 1000.
Sergey Gorokhov пишет: Уточните, а не в С++ тоже появляется 1000?
Думаю, в самом Lua все будет работать. Мне интересно, что это за номер, с чем это может быть связано? Та же проблема ранее была при открытии стакана с включенной панелью инструментов.
Цитата
может быть проблема в _luafix?
По поводу _luafix -- это класс-обертка стандартных функций lua и qlua. Возможно проблема в ней, но мне не понятен смыл ошибки, по-этому не знаю где искать проблему.
В отладчике в поле Output появляются следующие строки: First-chance exception at 0x07306684 (qlua.dll) in info.exe: 0xC0000005: Access violation reading location 0x0000001C. First-chance exception at 0x75B0C41F in info.exe: Microsoft C++ exception: cSEHException at memory location 0x00C7C778.
Ниже привожу мой код получения стакана на с++. Проверьте, пожалуйста, кто может. Будет ли возникать данная ошибка у вас. Может я в коде что-то не то делаю?
Код
typedef map<string, string> ROW;
typedef map<int, ROW> TABL;
int lua_OnQuote(lua_State *st)
{
try
{
int top = lua_gettop(st);
if (top == 0) return 0;
string sec_code = lua_tostring(st, -1);// qlua.ToString(-1); // код бумаги
string class_code = lua_tostring(st, -2);// qlua.ToString(-2);// код класса
//Quote quote = qlua.getQuoteLevel2(class_code, sec_code);
top = lua_gettop(st);
lua_getglobal(st, "getQuoteLevel2");
lua_pushstring(st, class_code.c_str());
lua_pushstring(st, sec_code.c_str());
lua_pcall(st, 2, 1, 0);
int top2 = lua_gettop(st);
lua_pushnil(st);
string key; // ключ
int bid_count;
int offer_count;
TABL bid; // массив bid
TABL offer; // массиы offer
while (lua_next(st, top2) != 0) {
int type = lua_type(st, -1);
if (type == LUA_TNUMBER) key = to_string(lua_tointeger(st, -2));
else key = lua_tostring(st, -2);
type = lua_type(st, -1);
switch (type)
{
case LUA_TSTRING:
if (key == "bid_count") bid_count = lua_tointeger(st, -1);
else offer_count = lua_tointeger(st, -1);
break;
case LUA_TTABLE:
int top3 = lua_gettop(st);
int len;
if (key == "bid") len = bid_count;
else len = offer_count;
for (int j = 1; j <= len; j++)
{
lua_rawgeti(st, top3, j);
// получаем ячейки стакана
int top4 = lua_gettop(st);
lua_pushnil(st);
ROW row;
while (lua_next(st, top4) != 0) {
string key2 = lua_tostring(st, -2);
row[key2] = lua_tostring(st, -1);
lua_pop(st, 1);
}
if (key == "bid") bid[j] = row;
else offer[j] = row;
lua_pop(st, 1);
}
break;
}
lua_pop(st, 1);
}
lua_pop(st, 1);
if (0 != top - lua_gettop(st) - 1) LOG_ERROR << "Lua stack is changed!\n getTop=" << lua_gettop(st);
}
catch (...)
{
LOG_ERROR << "Ошибка в стакане";
//lua_unlock(_luafix.lua);
}
return 0;
}
На сколько становится понятно, Вы говорите что проблема заключается в появлении значения "1000" в переменной sec_code. Если так, нужно смотреть выше, что попадает в эту переменную и от куда оно туда попадает, а не то где Вы с ней работаете.
if (top == 0) return 0; поставьте здесь проверку значения на вершине стека на тип кода или вывод в лог файл string sec_code = lua_tostring(st, -1);// qlua.ToString(-1); // код бумаги
Николай, я сделал как вы написали. Тип кода всегда равен 4, т.е. строка. Надеюсь я правильно Вас понял. Constantin, спасибо за замечания, исправил код как Вы написали. Это помогло убрать вылеты КВИКА.
Более детальное изучение показало, что во время чтения ячейки price или quantity при выполнении функции while (lua_next(st, top4) != 0) qlua.dll вызывает исключение: First-chance exception at 0x07306684 (qlua.dll) in info.exe: 0xC0000005: Access violation reading location 0x0000001C. First-chance exception at 0x75B0C41F in info.exe: Microsoft C++ exception: cSEHException at memory location 0x00C7C778.
После этого, событие int lua_OnQuote(lua_State *st) вызывается повторно и оно содержит на вершине стека значение 1000.
Данная проблема возникает, то при интенсивном изменении стакана, например при падении рынка.
Решил проверить получение стакана из lua скрипта. Ниже мой код.
Код
function main()
while not stopped do sleep(1000) end
end
function OnQuote(class_code, sec_code)
tb=getQuoteLevel2(class_code, sec_code)
for i=1,tb.bid_count,1 do
b = tb.bid[i].price
q = tb.bid[i].quantity
end
for i=1,tb.offer_count,1 do
b = tb.bid[i].price << на эту строку ругается "test.lua:43: attempt to index field '?' (a nil value)"
q = tb.bid[i].quantity
end
end
Запускаем данный код, открываем 10 стаканов и ждем пока рынок начнет сильное движение. В результате получаем ошибку скрипта
Код
test.lua:43: attempt to index field '?' (a nil value)
Ошибка иногда выскакивает сразу, иногда в течении 10 минут. Проверьте, кто-нибудь у себя.
NiKO, посмотри какие типы имеют bid_count и offer_count. Quik любит возвращать многие числовые параметры в строковом виде. Интересно как это повлияет на цикл. Возможно никак. Можно попробовать преобразовать tonumber(), если тип строковый.
А так у тебя во втором цикле ошибка: замени "tb.bid[i]" на "tb.offer[i]".
Николай Камынин, Вы продвинули меня вперед по проблеме. Я сменил sleep(1000) на sleep(999). Изменился вывод ошибки на 999. Что это может значить я пока не понимаю.
это значит, что на вершине стека лежит эта константа. попробуйте поставить проверку типа после вызова функции обращения к стакану. lua_pcall(st, 2, 1, 0); весьма возможно что функция ничего не вернула или вернула nil, а вы пытаетесь что-то извлекать из стека.
На сколько я понял, проблема заключалась в синхронизации потоков main() и onQuote(). Дело в том, что при чтении таблицы в событии onQuote(), одновременно в теле main() вызывалась функция sleep(1000) в результате стек портился и функция lua_next в onQuote обращалась по неправильному адресу. В результате этого, возникало исключение и возвращало на вершину стека время в милисекундах, которое я задавал в sleep(). Если я не прав, поправьте меня.
Сейчас все работает как часы! Николай, спасибо! Я уже больше месяца решаю эту проблему =). Пошел отмечать =)